HDU Today(HDU 2112)

题目链接

题目描述

经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强。这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市浬浦镇陶姚村买了个房子,开始安度晚年了。
这样住了一段时间,徐总对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格)。
徐总经常会问蹩脚的英文问路:“Can you help me?”。看着他那迷茫而又无助的眼神,热心的你能帮帮他吗?
请帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。

输入格式

输入数据有多组,每组的第一行是公交车的总数N(0<=N<=10000);
第二行有徐总的所在地start,他的目的地end;
接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
note:一组数据中地名数不会超过150个。
如果N==-1,表示输入结束。

输出格式

如果徐总能到达目的地,输出最短的时间;否则,输出“-1”。

输入样例

6
xiasha westlake
xiasha station 60
xiasha ShoppingCenterofHangZhou 30
station westlake 20
ShoppingCenterofHangZhou supermarket 10
xiasha supermarket 50
supermarket westlake 10
-1

输出样例

50

分析

本题主要是用set和map函数进行建图,另外注意题目可能描述不清晰,如果建有向图会WA,所以必须建无向图,以下是dijkstra、SPFA和SPFA(SLF优化)算法的源码。

源程序

Dijkstra算法

#include <bits/stdc++.h>
#define MAXN 155
#define MAXM 10005
using namespace std;
struct Edge{	//链式前向星 
	int v,w,next;
	Edge(){};
	Edge(int _v,int _w,int _next){
		v=_v,w=_w,next=_next;
	};
	bool operator <(const Edge tmp)const{
		return w>tmp.w;
	};
}edge[MAXM*2];
int EdgeCount,head[MAXN];
int n,cnt,tim[MAXM],dis[MAXN];
string s,t,a[MAXM],b[MAXM];
bool used[MAXN];
void addEdge(int u,int v,int w)	//链式前向星加边 
{
	edge[++EdgeCount]=Edge(v,w,head[u]);
	head[u]=EdgeCount;
}
void Dijkstra(int start,int end)
{
	priority_queue<Edge> Q;
	memset(dis,0x3f,sizeof(dis));
	memset(used,false,sizeof(used));
	dis[start]=0;
	Q.push(Edge{start,0,0});
	while(!Q.empty()){
		int u=Q.top().v;Q.pop();
		if(used[u])continue;
		used[u]=true;
		for(int i=head[u];i;i=edge[i].next){
			int v=edge[i].v,w=edge[i].w;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				Q.push(Edge{v,dis[v],0});
			}
		}
	}
	if(dis[end]==0x3f3f3f3f)printf("-1\n");
	else printf("%d\n",dis[end]);
}
int main()
{
	while(cin>>n&&n!=-1){
		int cnt=0;
		set<string> S;
		map<string,int> M;
		cin>>s>>t;
		S.insert(s),S.insert(t);	//建立set	
		for(int i=1;i<=n;i++){
			cin>>a[i]>>b[i]>>tim[i];
			S.insert(a[i]),S.insert(b[i]);
		}
		set<string>::iterator it;	//建立map 
		for(it=S.begin();it!=S.end();it++){
			M[*it]=++cnt;
		}
		memset(head,0,sizeof(head));	//初始化 
		EdgeCount=0;
		for(int i=1;i<=n;i++){	//建图 
			int u=M[a[i]],v=M[b[i]],w=tim[i];
			addEdge(u,v,w);
			addEdge(v,u,w);
		}
		Dijkstra(M[s],M[t]);
	}
	return 0;
}

SPFA算法

#include <bits/stdc++.h>
#define MAXN 155
#define MAXM 10005
using namespace std;
struct Edge{	//链式前向星 
	int v,w,next;
	Edge(){};
	Edge(int _v,int _w,int _next){
		v=_v,w=_w,next=_next;
	};
}edge[MAXM*2];
int EdgeCount,head[MAXN];
int n,cnt,tim[MAXM],dis[MAXN],ven[MAXN],nums[MAXN];
string s,t,a[MAXM],b[MAXM];
void addEdge(int u,int v,int w)	//链式前向星加边 
{
	edge[++EdgeCount]=Edge(v,w,head[u]);
	head[u]=EdgeCount;
}
void SPFA(int start,int end)
{
	queue<int> Q;
	memset(dis,0x3f,sizeof(dis));	//初始化 
	memset(ven,0,sizeof(ven));
//	memset(nums,0,sizeof(nums));
	dis[start]=0;
	ven[start]=nums[start]=1;
	Q.push(start);
	while(!Q.empty()){
		int u=Q.front();Q.pop();
		ven[u]=0;
		for(int i=head[u];i;i=edge[i].next){
			int v=edge[i].v,w=edge[i].w;
			if(dis[v]>dis[u]+w){	//更新最短巨鹿 
				dis[v]=dis[u]+w;
				if(!ven[v]){	//不在队列中 
					Q.push(v);
					ven[v]=1;
//					nums[v]++;
//					if(nums>cnt)return false;	//顶点访问次数超出cnt 
				}
			}
		}
	}
	if(dis[end]==0x3f3f3f3f)printf("-1\n");
	else printf("%d\n",dis[end]);
//	return false;
}
int main()
{
	while(cin>>n&&n!=-1){
		set<string> S;
		map<string,int> M;
		cin>>s>>t;
		S.insert(s),S.insert(t);	//建立set	
		for(int i=1;i<=n;i++){
			cin>>a[i]>>b[i]>>tim[i];
			S.insert(a[i]),S.insert(b[i]);
		}
		cnt=0;
		set<string>::iterator it;	//建立map 
		for(it=S.begin();it!=S.end();it++){
			M[*it]=++cnt;
		}
		memset(head,0,sizeof(head));	//初始化 
		EdgeCount=0;
		for(int i=1;i<=n;i++){	//建图 
			int u=M[a[i]],v=M[b[i]],w=tim[i];
			addEdge(u,v,w);
			addEdge(v,u,w);
		}
		SPFA(M[s],M[t]);
	}
	return 0;
}

SPFA算法SLF优化

#include <bits/stdc++.h>
#define MAXN 155
#define MAXM 10005
using namespace std;
struct Edge{	//链式前向星 
	int v,w,next;
	Edge(){};
	Edge(int _v,int _w,int _next){
		v=_v,w=_w,next=_next;
	};
}edge[MAXM*2];
int EdgeCount,head[MAXN];
int n,cnt,tim[MAXM],dis[MAXN],ven[MAXN],nums[MAXN];
string s,t,a[MAXM],b[MAXM];
void addEdge(int u,int v,int w)	//链式前向星加边 
{
	edge[++EdgeCount]=Edge(v,w,head[u]);
	head[u]=EdgeCount;
}
void SPFA(int start,int end)
{
	deque<int> Q;
	memset(dis,0x3f,sizeof(dis));	//初始化 
	memset(ven,0,sizeof(ven));
//	memset(nums,0,sizeof(nums));
	dis[start]=0;
	ven[start]=nums[start]=1;
	Q.push_back(start);
	int k;	//记录双端队列中个数 
	while((k=Q.size())){
		int u=Q.front();Q.pop_front();
		ven[u]=0;
		for(int i=head[u];i;i=edge[i].next){
			int v=edge[i].v,w=edge[i].w;
			if(dis[v]>dis[u]+w){	//更新最短巨鹿 
				dis[v]=dis[u]+w;
				if(!ven[v]){	//不在队列中 
					if(k>1&&dis[v]>dis[Q.front()])Q.push_front(v);
					else Q.push_back(v);
					ven[v]=1;
//					nums[v]++;
//					if(nums>cnt)return false;	//顶点访问次数超出cnt 
				}
			}
		}
	}
	if(dis[end]==0x3f3f3f3f)printf("-1\n");
	else printf("%d\n",dis[end]);
//	return false;
}
int main()
{
	while(cin>>n&&n!=-1){
		set<string> S;
		map<string,int> M;
		cin>>s>>t;
		S.insert(s),S.insert(t);	//建立set	
		for(int i=1;i<=n;i++){
			cin>>a[i]>>b[i]>>tim[i];
			S.insert(a[i]),S.insert(b[i]);
		}
		cnt=0;
		set<string>::iterator it;	//建立map 
		for(it=S.begin();it!=S.end();it++){
			M[*it]=++cnt;
		}
		memset(head,0,sizeof(head));	//初始化 
		EdgeCount=0;
		for(int i=1;i<=n;i++){	//建图 
			int u=M[a[i]],v=M[b[i]],w=tim[i];
			addEdge(u,v,w);
			addEdge(v,u,w);
		}
		SPFA(M[s],M[t]);
	}
	return 0;
}
发布了19 篇原创文章 · 获赞 0 · 访问量 124

猜你喜欢

转载自blog.csdn.net/weixin_43960284/article/details/105274213