L2-001. 紧急救援
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出4个正整数N、M、S、D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出不同的最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出首尾不能有多余空格。
输入样例:4 5 0 3 20 30 40 10 0 1 1 1 3 2 0 3 3 0 2 2 2 3 2输出样例:
2 60 0 1 3
代码如下:
/*
解题思路:
就是dijkstra;
注意点:
第一点:当代价相同的时候,到达该点的数目 k[j] = k[j] + k[k1];
第二点:当你的代价小于它的时候,k[k] = k[i];
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;
int preoder[505];
int v[505],path[505][505],step[505],k[505],p[505];
int n,m;
int inf = 99999999,ff,si,sj;
void dj()
{
///标记确定点的点
int un[550];
memset(un,0,sizeof(un));
///初始化,开始点为si,到达的数目为1,前驱的能叫到的人员为v[si]
k[si] = 1;
step[si] = 0;
preoder[si] = v[si];
for(int i=0; i<n; i++)
{
///寻找step[j],最小的点,也就是到那点代价最小的点,开始
int k1 =-1,t = inf;
for(int j=0; j<n; j++)
{
if(un[j] == 0 && step[j] < t)
{
k1 = j;
t = step[j];
}
}
///标记确定的点
un[k1] = 1;
for(int j=0; j<n; j++)
{
///表示该点是不是确定的,或者二者之间有没有路径
if(un[j] == 1 || path[k1][j] == -1)
continue;
if(step[j] == step[k1] + path[k1][j])
{
k[j] = k[k1] + k[j];
if(preoder[j] < v[j] + preoder[k1])
{
preoder[j] = v[j] + preoder[k1];
p[j] = k1;
}
}
else if(step[j] > step[k1] + path[k1][j])
{
k[j] = k[k1];
step[j] = step[k1] + path[k1][j];
preoder[j] = v[j] + preoder[k1];
p[j] = k1;
}
}
}
}
void printPath(int v) {
if(v == si) {
printf("%d", v);
return ;
}
printPath(p[v]);
printf(" %d", v);
}
int main()
{
int si,sj;
///表示路径的连通
memset(path,-1,sizeof(path));
///表示前驱
memset(preoder,0,sizeof(preoder));
///表示达到i点的路径数目
memset(k,0,sizeof(k));
///开始模拟
scanf("%d%d%d%d",&n,&m,&si,&sj);
///表示不可达
for(int i=0; i<n; i++)
step[i] = inf;
///输入给点值
for(int i=0; i<n; i++)
scanf("%d",&v[i]);
int x,y,z;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&x,&y,&z);
path[x][y] = z;
path[y][x] = z;
}
dj();
printf("%d %d\n",k[sj],preoder[sj]);
printPath(sj);
printf("\n");
return 0;
}