pta l2-1紧急救援(Dijkstra)

时间:2023-03-10 03:05:43
pta l2-1紧急救援(Dijkstra)

题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840

题意:给n个城市,m条边,每个城市有一定数量的救援队,起点s,终点d,求s到d的最短距离,同时路上尽可能召集更多的救援队。

思路:单元最短路径问题,用dijkstra算法,需要增加一维表示救援队的数量,还有就是题目要求输出最短路径的条数,用ct数组来表示,另外用pre数组表示路径中的上一个结点,用来回溯路径并打印。

AC代码:

 #include<bits/stdc++.h>
using namespace std; const int inf=0x3f3f3f3f;
int n,m,s,d;
int a[][],jyd[],pre[],dis[],num[],vis[],ct[]; void dijkstra(){
dis[s]=,pre[s]=-,num[s]=jyd[s],vis[s]=,ct[s]=;
while(){
int Min=inf,k;
for(int i=;i<n;++i)
if(!vis[i]&&dis[i]<Min)
Min=dis[i],k=i;
if(k==d||Min==inf) break;
vis[k]=;
for(int i=;i<n;++i){
if(!vis[i]&&dis[i]>dis[k]+a[k][i]){
dis[i]=dis[k]+a[k][i];
num[i]=num[k]+jyd[i];
ct[i]=ct[k];
pre[i]=k;
}
else if(!vis[i]&&dis[i]==dis[k]+a[k][i]){
ct[i]+=ct[k];
if(num[i]<num[k]+jyd[i]){
num[i]=num[k]+jyd[i];
pre[i]=k;
}
}
}
}
} void print(int p){
if(p>=){
print(pre[p]);
if(p==s) printf("%d",p);
else printf(" %d",p);
}
} int main(){
scanf("%d%d%d%d",&n,&m,&s,&d);
for(int i=;i<n;++i)
for(int j=;j<n;++j)
a[i][j]=inf;
for(int i=;i<n;++i)
scanf("%d",&jyd[i]),dis[i]=inf,pre[i]=-;
while(m--){
int t1,t2,t3;
scanf("%d%d%d",&t1,&t2,&t3);
a[t1][t2]=a[t2][t1]=t3;
}
for(int i=;i<n;++i){
if(a[s][i]<inf)
dis[i]=a[s][i],num[i]=jyd[s]+jyd[i],pre[i]=s,ct[i]=;
}
dijkstra();
printf("%d %d\n",ct[d],num[d]);
print(d);
printf("\n");
return ;
}