题目描述
经过锦囊相助,海东集团终于度过了危机,从此,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;
}