PTA L2-001 紧急救援-最短路(Dijkstra)多条最短路找最优解并输出路径 团体程序设计天梯赛-练习集

 

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出4个正整数N、M、S、D,其中N(2)是城市的个数,顺便假设城市的编号为0 ~ (;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

 

 

这道题我用带pair的优先队列的迪杰斯特拉跑,保存所有满足条件的路径,然后dfs找出所有路径并找出每条路径的人数,然后输出来最优的。但是怎么都过不去第二个样例,百度了一下,发现有人和我一样的问题,怎么改都过不了,最后死心了,换了一个就过了。。。

贴一下我错误的代码,谁来拯救一下我。。。

 

错误代码(过不了第二个样例):

  1 //紧急救援-wa2
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<bitset>
  7 #include<cassert>
  8 #include<cctype>
  9 #include<cmath>
 10 #include<cstdlib>
 11 #include<ctime>
 12 #include<deque>
 13 #include<iomanip>
 14 #include<list>
 15 #include<map>
 16 #include<queue>
 17 #include<set>
 18 #include<stack>
 19 #include<vector>
 20 using namespace std;
 21 typedef long long ll;
 22 typedef long double ld;
 23 typedef pair<int,int> pii;
 24 
 25 const double PI=acos(-1.0);
 26 const double eps=1e-6;
 27 const ll mod=1e9+7;
 28 const int inf=0x3f3f3f3f;
 29 const int maxn=1e6+100;
 30 const int maxm=100+10;
 31 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 32 
 33 int n,m,st,ed;
 34 int cnt=0,head[maxn<<2],p[maxn];
 35 bool vist[maxn];
 36 int dis[maxn],val[maxn];
 37 priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
 38 vector<int> path[maxn];
 39 
 40 struct node{
 41     int v,nex;
 42     int w,num;
 43 }edge[maxn<<2];
 44 
 45 void add(int u,int v,ll w)
 46 {
 47     edge[cnt].v=v;
 48     edge[cnt].w=w;
 49     edge[cnt].nex=head[u];
 50     head[u]=cnt++;
 51 }
 52 
 53 void dijkstra(int s)
 54 {
 55     dis[s]=0;//到自己的最短距离直接设为0
 56 //    sum[s]=val[s];
 57     q.push(make_pair(0,s));
 58     while(!q.empty()){//队列非空
 59         int u=q.top().second;q.pop();
 60         if(vist[u]) continue;
 61         vist[u]=true;
 62         if(u==ed+1) break;
 63         for(int i=head[u];~i;i=edge[i].nex){
 64             int v=edge[i].v;
 65 //            ll s=val[v];
 66             int w=edge[i].w;
 67             if(vist[v]) continue;
 68             if(dis[v]>dis[u]+w){//满足条件更新距离
 69                 dis[v]=dis[u]+w;
 70 //                sum[v]=sum[u]+s;
 71 //                p[v]=u;//保存路径
 72                 path[v].clear();
 73                 path[v].push_back(u);
 74                 q.push(make_pair(dis[v],v));//把更新完的值压入队列
 75             }
 76             else if(dis[v]==dis[u]+w){
 77                 path[v].push_back(u);
 78                 q.push(make_pair(dis[v],v));
 79             }
 80         }
 81     }
 82 }
 83 
 84 vector<int> minPath[maxn];
 85 int sum=0;
 86 int number=1;
 87 
 88 void dfs(int s)
 89 {
 90     sum+=val[s];
 91     minPath[number].push_back(s);
 92     if(s==st+1){
 93         minPath[number].push_back(sum);
 94         number++;
 95         minPath[number].push_back(ed+1);
 96         sum=val[ed+1];
 97     }
 98     for(int i=0;i<path[s].size();i++){
 99         dfs(path[s][i]);
100     }
101 }
102 
103 int main()
104 {
105     ios;
106 //    memset(head,-1,sizeof(head));//初始化数组
107 //    memset(vist,false,sizeof(vist));
108 //    memset(dis,inf,sizeof(dis));
109     cin>>n>>m>>st>>ed;
110     for(int i=0;i<2*n+100;i++){
111         head[i]=-1;
112         vist[i]=false;
113         dis[i]=inf;
114     }
115     for(int i=1;i<=n;i++)
116         cin>>val[i];
117     for(int i=1;i<=m;i++){
118         int u,v;ll w;
119         cin>>u>>v>>w;
120         add(u+1,v+1,w);
121         add(v+1,u+1,w);//无向图相互可达 有向图一次就好
122     }
123     dijkstra(st+1);
124     int i=ed+1;
125 //    ans.push_back(ed+1);
126 //    while(1){
127 //        i=p[i];
128 //        ans.push_back(i);
129 //        if(i==st+1) break;
130 //    }
131 //    cout<<ans.size()<<endl;
132 //    for(int i=(int)ans.size()-1;i>=0;i--)
133 //        cout<<ans[i]-1<<" ";
134 //    cout<<endl;
135     dfs(ed+1);
136     int pos;
137     int maxx=-inf;
138     for(int i=1;i<number;i++){
139        int cnt=minPath[i][minPath[i].size()-1];
140 //        cout<<cnt<<endl;
141         if(maxx<cnt){
142             maxx=cnt;
143             pos=i;
144         }
145     }
146     cout<<number-1<<" "<<maxx<<endl;
147     int len=minPath[pos].size();
148 //    cout<<len<<endl;
149     for(int i=len-1-1;i>0;i--)
150         cout<<minPath[pos][i]-1<<" ";
151     cout<<minPath[pos][0]-1<<endl;
152 //    cout<<dis[ed+1]<<endl;
153 //    cout<<sum[ed+1]<<endl;
154     return 0;
155 }
View Code

 

换了一个思路,代码短一些。

正确的代码:

 1 //again
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 typedef long long ll;
 5 const int maxn=5e2+5;
 6 const int maxm=15;
 7 const int inf=0x3f3f3f3f;
 8 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 9 
10 struct Edge{
11     int v,w;
12 
13     Edge(int v1=0,int w1=0){
14         v=v1,w=w1;
15     }
16 
17     friend bool operator <(Edge a,Edge b){
18         return a.w>b.w;
19     }
20 
21 };
22 
23 int n,m,s,d;
24 bool vis[maxn];
25 int dis[maxn],pnum[maxn],rnum[maxn],num[maxn],pre[maxn];//pnum为人数,rnum为路径,num为各城市的人,pre为保存前继节点
26 vector<Edge> e[maxn];
27 priority_queue<Edge> pq;
28 
29 void dijkstra()
30 {
31     memset(dis,inf,sizeof(dis));
32     dis[s]=0,rnum[s]=1,pnum[s]=num[s],pre[s]=-1;
33     pq.push(Edge(s,0));
34     while(!pq.empty()){
35         int u=pq.top().v;
36         pq.pop();
37         if(vis[u]) continue;
38         vis[u]=true;
39         if(u==d) break;
40         for(int i=0;i<e[u].size();i++){
41             int v=e[u][i].v,w=e[u][i].w;
42             if(!vis[v]){
43                 if(dis[u]+w<dis[v]){
44                     dis[v]=dis[u]+w;
45                     rnum[v]=rnum[u];
46                     pre[v]=u;
47                     pnum[v]=pnum[u]+num[v];
48                     pq.push(Edge(v,dis[v]));
49                 }
50                 else if(dis[u]+w==dis[v]){
51                     rnum[v]+=rnum[u];//上一条的都加进来
52                     if(pnum[u]+num[v]>pnum[v]){//如果有更大的值,就进行更新
53                         pnum[v]=pnum[u]+num[v];
54                         pre[v]=u;
55                     }
56                 }
57             }
58         }
59     }
60 }
61 
62 stack<int> ans;
63 
64 int main(){
65     ios;
66     cin>>n>>m>>s>>d;
67     for(int i=0;i<n;i++)
68         cin>>num[i];
69     for(int i=1;i<=m;i++){
70         int u,v,w;
71         cin>>u>>v>>w;
72         e[u].push_back(Edge(v,w));
73         e[v].push_back(Edge(u,w));
74     }
75     dijkstra();
76     cout<<rnum[d]<<" "<<pnum[d]<<endl;
77     while(d!=-1){
78         ans.push(d);
79         d=pre[d];
80     }
81     while(ans.size()>1){
82         cout<<ans.top()<<" ";
83         ans.pop();
84     }
85     cout<<ans.top();
86     return 0;
87 }

 

参考:

利用Dijkstra算法实现记录每个结点的所有最短路径

团体程序设计天梯赛-练习集-L2-001 紧急救援(dij最短路)

 

posted @ 2019-03-29 20:54  ZERO-  阅读(385)  评论(0编辑  收藏  举报