PTA L2-001 紧急救援

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

输入:

输入第一行给出4个正整数N、M、S、D,其中N(0-500)是城市的个数,顺便假设城市的编号为0 ~ N-1M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。

第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,

中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

输出:

第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。

分析:本质上还是用dij做的最短路问题,但需要添加些东西,我们可以用num数组表示从起点到i的最短路径条数,w数组表示救援队数量

同时最用dij做最短路的时候,把最短路径上每个城市的前驱用pre数组记录下来

这样,在更新最短路时,如果dis[e.to]>dis[v]+e.cost  就需要将v和e.to连接起来,那么num[e.to]就应该和num[v]保持一致,w[e.to]=w[v]+a[e.to]

除了大于的情况,对于dis[e.to]==dis[v]+e.cost,我们也需要考虑,因为e.to的最短路径条数除了本身的,还有从v连接过来的,则num[e.to]+=num[v]

如果w[v]+a[e.to]>w[e.to],那么w[e.to]=w[v]+a[e.to],因为要保证救援队数量最多

另外每当连路径的时候记得把pre数组录入一下,最后递归输出即可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int inf=1<<30;
 4 typedef long long ll;
 5 typedef pair<int,int> P;
 6 const double pi=acos(-1);
 7 const int mod=1e8+7;
 8 const int maxn=505;
 9 const int maxm=6300;
10 int dis[maxn];
11 int a[maxn],num[maxn],w[maxn],pre[maxn];//num数组是出发点到i点时拥有的路径的条数,w数组是救援队的数目 
12 struct edge{
13     int to,cost;
14 };
15 int x,y,z,n,m,s,d;
16 vector<edge> g[maxm];
17 void dij(int s){
18     priority_queue<P,vector<P>,greater<P> > que;
19     fill(dis,dis+maxn,inf);
20     dis[s]=0;
21     w[s]=a[s],num[s]=1;//初始化,到起始点救援队数量就是起始点本身救援队数量,路径也只有一条 
22     que.push({0,s});
23     while(!que.empty()){
24         P p=que.top();que.pop();
25         int v=p.second;
26         if(dis[v]<p.first) continue;
27         for(int i=0;i<g[v].size();i++){
28             edge e=g[v][i];
29             if(dis[e.to]>dis[v]+e.cost){//这种情况肯定要从v到e.to了 
30                 num[e.to]=num[v];
31                 w[e.to]=w[v]+a[e.to]; 
32                 dis[e.to]=dis[v]+e.cost;
33                 pre[e.to]=v;
34                 que.push({dis[e.to],e.to});
35             }
36             else if(dis[e.to]==dis[v]+e.cost){
37                 if(w[v]+a[e.to]>w[e.to]){w[e.to]=w[v]+a[e.to];pre[e.to]=v;} 
38                 num[e.to]+=num[v];    //还要再加上v点的            
39             }
40         }
41     }
42 }
43 void print(int c){
44     if(c==s){
45         cout<<s;return;
46     }
47     print(pre[c]);
48     cout<<" "<<c;
49 }
50 int main(){
51     scanf("%d%d%d%d",&n,&m,&s,&d);
52     for(int i=0;i<n;i++) scanf("%d",&a[i]);
53     for(int i=0;i<m;i++){
54         scanf("%d%d%d",&x,&y,&z);
55         g[x].push_back({y,z});
56         g[y].push_back({x,z});
57     }
58     dij(s);
59     cout<<num[d]<<" "<<w[d]<<endl;
60     print(d);
61     cout<<endl;
62     return 0;
63 }

猜你喜欢

转载自www.cnblogs.com/qingjiuling/p/10474820.html