PTA:L3-007 天梯地图

PTA:L3-007 天梯地图 

题解:

一开始题目没有看仔细,way = 1,代表单向,way = 0代表双向,不是没有路(很坑)。

两次Dijkstra,然后保存路径。

代码:

#include <bits/stdc++.h>
#define st first
#define sd second
using namespace std;
typedef pair<int,int>pii;
int const N = 500 + 10;
int const inf = 0x7f7f7f7f;
int n,m,s,t;
int dis[N],tim[N],num[N],path1[N],path2[N],a[N],b[N];   //记录路径的上一个点
struct Edge
{
	int v,time,len;
	Edge(int a,int b,int c):v(a),time(b),len(c){};
};
vector<Edge>G[N];
void Dijkstra1(int s,int t){   //求最快路线,相同找最短路线
	priority_queue<pii,vector<pii>,greater<pii> >q;
	for(int i=0;i<=n;i++)	tim[i] = dis[i] = inf;
	q.push(pii(0,s));
	tim[s] = dis[s] = 0;	path1[s] = -1;
	while(!q.empty()){
		pii p = q.top();	q.pop();
		int x = p.sd;
		if(tim[x] < p.st)	continue;
		for(int i=0;i<G[x].size();i++){
			Edge e = G[x][i];
			if(tim[e.v] > tim[x] + e.time){
				tim[e.v] = tim[x] + e.time;
				dis[e.v] = dis[x] + e.len;
				path1[e.v] = x;
				q.push(pii(tim[e.v],e.v));
			}else if(tim[e.v] == tim[x] + e.time){
				if(dis[e.v] > dis[x] + e.len){
					dis[e.v] = dis[x] + e.len;
					path1[e.v] = x;
				}
			}
		}
	}
}
void Dijkstra2(int s,int t){   //求最快路线,相同找最短路线
	priority_queue<pii,vector<pii>,greater<pii> >q;
	for(int i=0;i<=n;i++)	dis[i] = num[i] = inf;
	q.push(pii(0,s));
	dis[s] = 0,	num[s] = 0;	path2[s] = -1;
	while(!q.empty()){
		pii p = q.top();	q.pop();
		int x = p.sd;
		if(dis[x] < p.st)	continue;
		for(int i=0;i<G[x].size();i++){
			Edge e = G[x][i];
			if(dis[e.v] > dis[x] + e.len){
				dis[e.v] = dis[x] + e.len;
				num[e.v] = num[x] + 1;
				path2[e.v] = x;
				q.push(pii(dis[e.v],e.v));
			}else if(dis[e.v] == dis[x] + e.len){
				if(num[e.v] > num[x] + 1){
					num[e.v] = num[x] + 1;
					path2[e.v] = x;
				}
			}
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int v1,v2,way,len,time;
		scanf("%d%d%d%d%d",&v1,&v2,&way,&len,&time);
		G[v1].push_back(Edge(v2,time,len));
		if(!way)	G[v2].push_back(Edge(v1,time,len));
	}
	scanf("%d%d",&s,&t);
	Dijkstra1(s,t);
	Dijkstra2(s,t);
	int cnt1 = 0,	cnt2 = 0,	flag = false;
	for(int i=t;i!=-1;i=path1[i])	a[cnt1++] = i;
	for(int i=t;i!=-1;i=path2[i])	b[cnt2++] = i;
	if(cnt1 == cnt2){
		for(int i=0;i<cnt1;i++)	if(a[i] != b[i]){
			flag = true;    //路线不相同
			break;
		}	
	}else	flag = true;
	if(flag){
		printf("Time = %d: %d",tim[t],s);
		for(int i=cnt1-2;i>=0;i--)		printf(" => %d",a[i]);	printf("\n");
		printf("Distance = %d: %d",dis[t],s);
		for(int i=cnt2-2;i>=0;i--)		printf(" => %d",b[i]);	printf("\n");
	}else{
		printf("Time = %d; Distance = %d: %d",tim[t],dis[t],s);
		for(int i=cnt1-2;i>=0;i--)		printf(" => %d",a[i]);	printf("\n");
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值