6 xiasha westlake xiasha station 60 xiasha ShoppingCenterofHangZhou 30 station westlake 20 ShoppingCenterofHangZhou supermarket 10 xiasha supermarket 50 supermarket westlake 10 -1
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; }铭记错误!