题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840
题意:给n个城市,m条边,每个城市有一定数量的救援队,起点s,终点d,求s到d的最短距离,同时路上尽可能召集更多的救援队。
思路:单元最短路径问题,用dijkstra算法,需要增加一维表示救援队的数量,还有就是题目要求输出最短路径的条数,用ct数组来表示,另外用pre数组表示路径中的上一个结点,用来回溯路径并打印。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int inf=0x3f3f3f3f; 5 int n,m,s,d; 6 int a[505][505],jyd[505],pre[505],dis[505],num[505],vis[505],ct[505]; 7 8 void dijkstra(){ 9 dis[s]=0,pre[s]=-1,num[s]=jyd[s],vis[s]=1,ct[s]=1; 10 while(1){ 11 int Min=inf,k; 12 for(int i=0;i<n;++i) 13 if(!vis[i]&&dis[i]<Min) 14 Min=dis[i],k=i; 15 if(k==d||Min==inf) break; 16 vis[k]=1; 17 for(int i=0;i<n;++i){ 18 if(!vis[i]&&dis[i]>dis[k]+a[k][i]){ 19 dis[i]=dis[k]+a[k][i]; 20 num[i]=num[k]+jyd[i]; 21 ct[i]=ct[k]; 22 pre[i]=k; 23 } 24 else if(!vis[i]&&dis[i]==dis[k]+a[k][i]){ 25 ct[i]+=ct[k]; 26 if(num[i]<num[k]+jyd[i]){ 27 num[i]=num[k]+jyd[i]; 28 pre[i]=k; 29 } 30 } 31 } 32 } 33 } 34 35 void print(int p){ 36 if(p>=0){ 37 print(pre[p]); 38 if(p==s) printf("%d",p); 39 else printf(" %d",p); 40 } 41 } 42 43 int main(){ 44 scanf("%d%d%d%d",&n,&m,&s,&d); 45 for(int i=0;i<n;++i) 46 for(int j=0;j<n;++j) 47 a[i][j]=inf; 48 for(int i=0;i<n;++i) 49 scanf("%d",&jyd[i]),dis[i]=inf,pre[i]=-1; 50 while(m--){ 51 int t1,t2,t3; 52 scanf("%d%d%d",&t1,&t2,&t3); 53 a[t1][t2]=a[t2][t1]=t3; 54 } 55 for(int i=0;i<n;++i){ 56 if(a[s][i]<inf) 57 dis[i]=a[s][i],num[i]=jyd[s]+jyd[i],pre[i]=s,ct[i]=1; 58 } 59 dijkstra(); 60 printf("%d %d ",ct[d],num[d]); 61 print(d); 62 printf(" "); 63 return 0; 64 }