Problem Description
经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强。这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市浬浦镇陶姚村买了个房子,开始安度晚年了。
这样住了一段时间,徐总对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格)。
徐总经常会问蹩脚的英文问路:“Can you help me?”。看着他那迷茫而又无助的眼神,热心的你能帮帮他吗?
请帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。
这样住了一段时间,徐总对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格)。
徐总经常会问蹩脚的英文问路:“Can you help me?”。看着他那迷茫而又无助的眼神,热心的你能帮帮他吗?
请帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。
Input
输入数据有多组,每组的第一行是公交车的总数N(0<=N<=10000);
第二行有徐总的所在地start,他的目的地end;
接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
note:一组数据中地名数不会超过150个。
如果N==-1,表示输入结束。
第二行有徐总的所在地start,他的目的地end;
接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
note:一组数据中地名数不会超过150个。
如果N==-1,表示输入结束。
Output
如果徐总能到达目的地,输出最短的时间;否则,输出“-1”。
Sample Input
6 xiasha westlake xiasha station 60 xiasha ShoppingCenterofHangZhou 30 station westlake 20 ShoppingCenterofHangZhou supermarket 10 xiasha supermarket 50 supermarket westlake 10 -1
Sample Output
50 Hint: The best route is: xiasha->ShoppingCenterofHangZhou->supermarket->westlake 虽然偶尔会迷路,但是因为有了你的帮助 **和**从此还是过上了幸福的生活。 ――全剧终――
题意就是很多站台,求从起始站台出发到终点的最短路径并输出,只不过这题换成了字符串输入。学过STL的很快就可以联想到map,不过没学过的也不要紧,每人有每人的做法,我用的trie树(存储字符串最方便而且最快查找的应该就是trie树了吧!应该很容易想到),然后建了trie树之后就是赤裸裸的求最短路了,由于spfa更好理解并且代码也好写同时能够处理负权值更重要的是效率还高!因此,我比较喜欢的就敲了spfa,其实dij那个方法也不错,不过我更偏好spfa!
不过尽管是赤裸裸的最短路的题目,此题我还是wa了无数次/汗,找bug的时候真是头都搞的要破了,结果最后发现自己的字典树存储出了问题/爆汗。字典树存储方式多样,所以一时想都没想就照以前的思路随便敲了,结果到头来坑的还是自己,不过还好自己想出bug来了,以后还得多练习trie树,写法多变有时候一不小心搞错了都不知道错哪里了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include<algorithm>
#define max0 100000000
using namespace std;
struct node
{
node *next[52];
int num;
node()
{
num=-1;
memset(next,0,sizeof(next));
}
}root;
void inser(char *s,int num)
{
int k=0;
node *p=&root;
while(s[k])
{
int t;
if(s[k]>='a'&&s[k]<='z')
t=s[k]-'a';
else t=s[k]-'A'+26;
if(!p->next[t])
p->next[t]=new node;
p=p->next[t];
k++;
if(!s[k])
p->num=num;
}
}
int find(char *s)
{
int k=0;
node *p=&root;
while(s[k])
{
int t;
if(s[k]>='a'&&s[k]<='z')
t=s[k]-'a';
else t=s[k]-'A'+26;
if(!p->next[t])
return -1;
p=p->next[t];
k++;
}
return p->num;
}
int cc[200][200];
int dis[200],dl[100000];bool vis[200];
int spfa(int s,int e,int bj)
{
int r=0;
for(int i=0;i<bj;i++)
dis[i]=max0;
memset(vis,1,sizeof(vis));
dis[s]=0;
dl[r++]=s;
while(r)
{
// for(int i=0;i<r;i++)
// cout<<dl[i]<<' ';cout<<endl;
int x=dl[--r];
// cout<<x<<" rudui "<<endl;
vis[x]=1;
for(int i=0;i<bj;i++)
{
if(cc[x][i]<max0&&x!=i)
{
if(dis[x]+cc[x][i]<dis[i])
{
dis[i]=dis[x]+cc[x][i];//cout<<i<<":"<<dis[i]<<endl;
if(vis[i])
{
dl[r++]=i;
vis[i]=0;
}
}
}
}
// cout<<"dis:"<<dis[e]<<endl;cout<<endl;
}
return dis[e];
}
int main()
{
int n;
while(~scanf("%d",&n)&&n!=-1)
{
//memset(dl,0,sizeof(dl));
root.num=-1;
for(int i=0;i<52;i++)
root.next[i]=0;
for(int i=0;i<200;i++)
for(int j=0;j<200;j++)
{
if(i!=j)cc[i][j]=max0;else cc[i][j]=0;
}
char st[35],ed[35];
cin>>st>>ed;
int bj=0;
bool flag=0;
if(!strcmp(st,ed))
flag=1;
else
{
inser(st,bj++);
inser(ed,bj++);
}
for(int i=0;i<n;i++)
{
char tem1[35],tem2[35];int nn;
cin>>tem1>>tem2>>nn;
if(!flag)
{
int t1=find(tem1);
if(t1==-1)
inser(tem1,bj++),t1=find(tem1);
int t2=find(tem2);
if(t2==-1)
inser(tem2,bj++),t2=find(tem2);
//cout<<find(tem1)<<endl;
// cout<<find(tem2)<<endl;
if(nn<cc[t1][t2])
cc[t1][t2]=cc[t2][t1]=nn;
}
}
if(flag)printf("0\n");
else
{
int te=spfa(0,1,bj);
if(te==max0)
printf("-1\n");
else
printf("%d\n",te);
}
}
return 0;
}
我在此附上自己想出来的测试数据,仅供参考:
3
a asd
a asd 2
a as 3
a c 1
我刚开始的错误trie树代码:
void inser(char *s,int num)
{
int k=0;
node *p=&root;
while(s[k])
{
int t;
if(s[k]>='a'&&s[k]<='z')
t=s[k]-'a';
else t=s[k]-'A'+26;
if(!p->next[t])
p->next[t]=new node;
p=p->next[t];
if(p->num==-1)p->num=num;
k++;
}
}
int find(char *s)
{
int k=0;
node *p=&root;
while(s[k])
{
int t;
if(s[k]>='a'&&s[k]<='z')
t=s[k]-'a';
else t=s[k]-'A'+26;
if(!p->next[t])
return -1;
p=p->next[t];
k++;
}
return p->num;
}
铭记错误!