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

L2-001 紧急救援 (25 分)
 

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

输入格式:

输入第一行给出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找出所有路径并找出每条路径的人数,然后输出来最优的。但是怎么都过不去第二个样例,百度了一下,发现有人和我一样的问题,怎么改都过不了,最后死心了,换了一个就过了。。。

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

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

 //紧急救援-wa2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii; const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
const int inf=0x3f3f3f3f;
const int maxn=1e6+;
const int maxm=+;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int n,m,st,ed;
int cnt=,head[maxn<<],p[maxn];
bool vist[maxn];
int dis[maxn],val[maxn];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
vector<int> path[maxn]; struct node{
int v,nex;
int w,num;
}edge[maxn<<]; void add(int u,int v,ll w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].nex=head[u];
head[u]=cnt++;
} void dijkstra(int s)
{
dis[s]=;//到自己的最短距离直接设为0
// sum[s]=val[s];
q.push(make_pair(,s));
while(!q.empty()){//队列非空
int u=q.top().second;q.pop();
if(vist[u]) continue;
vist[u]=true;
if(u==ed+) break;
for(int i=head[u];~i;i=edge[i].nex){
int v=edge[i].v;
// ll s=val[v];
int w=edge[i].w;
if(vist[v]) continue;
if(dis[v]>dis[u]+w){//满足条件更新距离
dis[v]=dis[u]+w;
// sum[v]=sum[u]+s;
// p[v]=u;//保存路径
path[v].clear();
path[v].push_back(u);
q.push(make_pair(dis[v],v));//把更新完的值压入队列
}
else if(dis[v]==dis[u]+w){
path[v].push_back(u);
q.push(make_pair(dis[v],v));
}
}
}
} vector<int> minPath[maxn];
int sum=;
int number=; void dfs(int s)
{
sum+=val[s];
minPath[number].push_back(s);
if(s==st+){
minPath[number].push_back(sum);
number++;
minPath[number].push_back(ed+);
sum=val[ed+];
}
for(int i=;i<path[s].size();i++){
dfs(path[s][i]);
}
} int main()
{
ios;
// memset(head,-1,sizeof(head));//初始化数组
// memset(vist,false,sizeof(vist));
// memset(dis,inf,sizeof(dis));
cin>>n>>m>>st>>ed;
for(int i=;i<*n+;i++){
head[i]=-;
vist[i]=false;
dis[i]=inf;
}
for(int i=;i<=n;i++)
cin>>val[i];
for(int i=;i<=m;i++){
int u,v;ll w;
cin>>u>>v>>w;
add(u+,v+,w);
add(v+,u+,w);//无向图相互可达 有向图一次就好
}
dijkstra(st+);
int i=ed+;
// ans.push_back(ed+1);
// while(1){
// i=p[i];
// ans.push_back(i);
// if(i==st+1) break;
// }
// cout<<ans.size()<<endl;
// for(int i=(int)ans.size()-1;i>=0;i--)
// cout<<ans[i]-1<<" ";
// cout<<endl;
dfs(ed+);
int pos;
int maxx=-inf;
for(int i=;i<number;i++){
int cnt=minPath[i][minPath[i].size()-];
// cout<<cnt<<endl;
if(maxx<cnt){
maxx=cnt;
pos=i;
}
}
cout<<number-<<" "<<maxx<<endl;
int len=minPath[pos].size();
// cout<<len<<endl;
for(int i=len--;i>;i--)
cout<<minPath[pos][i]-<<" ";
cout<<minPath[pos][]-<<endl;
// cout<<dis[ed+1]<<endl;
// cout<<sum[ed+1]<<endl;
return ;
}

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

正确的代码:

 //again
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e2+;
const int maxm=;
const int inf=0x3f3f3f3f;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); struct Edge{
int v,w; Edge(int v1=,int w1=){
v=v1,w=w1;
} friend bool operator <(Edge a,Edge b){
return a.w>b.w;
} }; int n,m,s,d;
bool vis[maxn];
int dis[maxn],pnum[maxn],rnum[maxn],num[maxn],pre[maxn];//pnum为人数,rnum为路径,num为各城市的人,pre为保存前继节点
vector<Edge> e[maxn];
priority_queue<Edge> pq; void dijkstra()
{
memset(dis,inf,sizeof(dis));
dis[s]=,rnum[s]=,pnum[s]=num[s],pre[s]=-;
pq.push(Edge(s,));
while(!pq.empty()){
int u=pq.top().v;
pq.pop();
if(vis[u]) continue;
vis[u]=true;
if(u==d) break;
for(int i=;i<e[u].size();i++){
int v=e[u][i].v,w=e[u][i].w;
if(!vis[v]){
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
rnum[v]=rnum[u];
pre[v]=u;
pnum[v]=pnum[u]+num[v];
pq.push(Edge(v,dis[v]));
}
else if(dis[u]+w==dis[v]){
rnum[v]+=rnum[u];//上一条的都加进来
if(pnum[u]+num[v]>pnum[v]){//如果有更大的值,就进行更新
pnum[v]=pnum[u]+num[v];
pre[v]=u;
}
}
}
}
}
} stack<int> ans; int main(){
ios;
cin>>n>>m>>s>>d;
for(int i=;i<n;i++)
cin>>num[i];
for(int i=;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
e[u].push_back(Edge(v,w));
e[v].push_back(Edge(u,w));
}
dijkstra();
cout<<rnum[d]<<" "<<pnum[d]<<endl;
while(d!=-){
ans.push(d);
d=pre[d];
}
while(ans.size()>){
cout<<ans.top()<<" ";
ans.pop();
}
cout<<ans.top();
return ;
}

参考:

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

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

上一篇:微信设置URL之WebApi方式


下一篇:团体程序设计天梯赛-练习集L2-007. 家庭房产