L2-001. 紧急救援
时间限制
200 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出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
题目分析:让求相同的最短路有几条,还有到达目的地后做多的救援队数量,还有路中经过的点。用迪杰斯特拉做。记录路径用path数组,path[u]表示u的前驱结点,dp记录相同的最短路径,b标记数组,ha记录最大的救人队数
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define inf 0x3f struct node { int b,c,d; } s[200000]; int a[550]; int s1[1000][1000]; int b[550]; int dis[550]; int path[550]; int dp[550]; int ha[550]; int n,m,s2,d; int main() { scanf("%d%d%d%d",&n,&m,&s2,&d); for(int i=0; i<n; i++) scanf("%d",&a[i]); memset(s1,0x3f,sizeof(s1)); memset(dp,0,sizeof(dp)); memset(ha,0,sizeof(ha)); memset(dis,0,sizeof(dis)); memset(b,0,sizeof(b)); for(int i=0; i<m; i++) { scanf("%d%d%d",&s[i].b,&s[i].c,&s[i].d); s1[s[i].b][s[i].c]=min(s1[s[i].b][s[i].c],s[i].d); s1[s[i].c][s[i].b]=s1[s[i].b][s[i].c]; } b[s2]=1; for(int i=0; i<n; i++) { dis[i]=s1[s2][i]; path[i]=s2; dp[i]=1; ha[i]=a[i]+a[s2]; } for(int i=0; i<n; i++) { int minn=0x3f,u; for(int j=0; j<n; j++) { if(!b[j]&&dis[j]<minn) { minn=dis[j]; u=j; } } b[u]=1; for(int k=0; k<n; k++) { if(s1[u][k]<inf&&dis[k]>minn+s1[u][k]) { dis[k]=minn+s1[u][k]; path[k]=u; dp[k]=dp[u]; ha[k]=ha[u]+a[k]; } else if(s1[u][k]<inf&&dis[k]==minn+s1[u][k]) { dp[k]+=dp[u]; if(ha[k]<ha[u]+a[k]) { ha[k]=ha[u]+a[k]; path[k]=u; } } } } printf("%d %d\n",dp[d],ha[d]); int i=d; int we[1000]; memset(we,0,sizeof(we)); int p=0; while(i!=s2) { we[p++]=path[i]; i=path[i]; } for(int i=p-1;i>=0;i--) printf("%d ",we[i]); printf("%d",d); printf("\n"); }