作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出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
源码:
#include <stdio.h>
#include <stdlib.h>
#define INFINITY 1000000
#define MaxVertexNum 500 /* maximum number of vertices */
typedef int Vertex; /* vertices are numbered from 0 to MaxVertexNum-1 */
typedef int WeightType;
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv;
int Ne;
WeightType G[MaxVertexNum][MaxVertexNum];
};
typedef PtrToGNode MGraph;
MGraph ReadG(int N,int M)
{
MGraph G=(MGraph)malloc(sizeof(struct GNode));
G->Nv=N;
G->Ne=M;
int i,j;
for(i=0;i<G->Nv;i++)
{
for(j=0;j<G->Nv;j++)
{
G->G[i][j]=INFINITY;
if(i==j)
G->G[i][j]=0;
}
}
for(i=0;i<G->Ne;i++)
{
int a,b,x;
scanf("%d%d%d",&a,&b,&x);
G->G[a][b]=x;
G->G[b][a]=x;
}
return G;
}
void ShortestDist( MGraph Graph, int dist[], int count[], Vertex S ,int path[],int *team,const int *oldteam)
{
int i,j;
int ask[MaxVertexNum];
for(i=0;i<MaxVertexNum;i++)
ask[i]=0;
while(1)
{
int min=INFINITY;
int minindex=0;
int flag=1;
for(i=0;i<Graph->Nv;i++)
{
if(!ask[i])
{
flag=0;
if(dist[i]<=min)
{
minindex=i;
min=dist[i];
}
}
}
if(flag)break;
ask[minindex]=1;
for(i=0;i<Graph->Nv;i++)
{
if(Graph->G[minindex][i]!=INFINITY&&i!=minindex)
{
if((dist[minindex]+Graph->G[minindex][i])<dist[i])
{
if(!ask[i])
{
//dist更新,同时path,team更新
dist[i]=dist[minindex]+Graph->G[minindex][i];
count[i]=count[minindex];
path[i]=minindex;
team[i]=oldteam[i]+team[minindex];
}
}
else if((dist[minindex]+Graph->G[minindex][i])==dist[i])
{
//dist相等时,比较team,team大的那个是新的path
count[i]+=count[minindex];
if(team[i]<oldteam[i]+team[minindex]) {
team[i] = oldteam[i] + team[minindex];
path[i] = minindex;
}
}
}
}
}
for(i=0;i<Graph->Nv;i++)
{
if(dist[i]==INFINITY)
{
dist[i]=-1;
count[i]=0;
}
}
}
int main()
{
int N,M,S,D;
scanf("%d%d%d%d",&N,&M,&S,&D);
int team[N];
//team动态存储当前路径下的救援队总数
int oldteam[N];
//oldteam为固定的每个城市的救援队数目
int path[N];
//最优路径存储
int count[N];
//最短路径条数
int dist[N];
//最短路径长度
int i;
for(i=0;i<N;i++)
{
scanf("%d",&team[i]);
oldteam[i]=team[i];
count[i]=0;
path[i]=-1;
dist[i]=INFINITY;
if(i==S)
count[i]=(dist[i]=0)+1;
}
MGraph G=ReadG(N,M);
ShortestDist( G,dist, count,S,path,team,oldteam);
printf("%d %d\n",count[D],team[D]);
//路径逆序输出
int stack[MaxVertexNum+1];
i=D;
int top=-1;
stack[++top]=i;
while(path[i]!=-1)
{
stack[++top]=path[i];
i=path[i];
}
int first=1;
while(top!=-1)
{
if(first==1)
{
printf("%d",stack[top--]);
first++;
}
else
printf(" %d",stack[top--]);
}
printf("\n");
return 0;
}