今天挺高兴的,因为第一:我A了自己的第一道AC自动机的题目:hdu 2222;第二:我发现了自己写的字典树的代码一直以来的错误;第三:我发现了用地杰斯特拉写的最短路的算法需要注意的地方。哈哈!!!!
题意:容易理解...
分析:这道题可以说是坑得我死去活来,并不是因为它有多难,其实就是一道名副其实的水题。但是由于我的基本功出现了问题导致了各种错误,开始我是怕暴力会超时,所以我选择了用字典树来做,但是由于我的粗心:没看清地名中既有大写又有小写,所以就是一直RunTime Error,后来经过再次读题,发现了错误,通过此我以后应该把题目看清楚;然后就是我的字典树一直错的地方了,等下我会在代码中注明,出现的错误是Memory Limit Exceeded,我以为字典树做不了;于是我索性用暴力来做下,就是每出现一个字符串就和前面的所有字符串比较一次,我以为顶多是超时,但是出乎我意料的是Wrong Answer,后来经过仔细的找错误,终于被我找到了错误,哈哈!!!这个题其实用暴力也可以做,但是我觉得用字典树更好吧,因为可以少很多时间啊!!!
代码实现:
字典树+dis实现:
#include<stdio.h> #include<string.h> #include<stdlib.h> int n,a[151][151],nima,visited[151]; struct node{ int num; struct node *next[52]; node() { memset(next,NULL,sizeof(next)); num=0; } }; struct node *root; int build(char *str)//字典树 { struct node *p=root,*t;//这里害得我一直是超内存,我开始的时候*p=new node,然后是p=root无语了!! int temp; for(;*str!='\0';str++) { if(*str>='a'&&*str<='z') temp=*str-'A'-6; else temp=*str-'A'; if(p->next[temp]==NULL) p->next[temp]=new node; p=p->next[temp]; } if(p->num) return p->num; else { p->num=nima; nima++; return p->num; } } void dis() { int i,j,min,depth[151],flag,cao=0; for(i=2;i<=n;i++) depth[i]=a[1][i]; visited[1]=0; for(i=2;i<=n;i++) { min=100000000; flag=0;//开始的时候这里没有的,当出发地到目的地没有路径是就错了!!! for(j=2;j<=n;j++) if(min>depth[j]&&visited[j]) { min=depth[j]; flag=j; } if(flag==2) { printf("%d\n",min); cao=1; break; } visited[flag]=0; if(flag) for(j=2;j<=n;j++) { if(visited[j]&&depth[j]>(depth[flag]+a[flag][j])) depth[j]=depth[flag]+a[flag][j]; } } if(cao==0) printf("-1\n"); } void del(struct node *tree) { int i; for(i=0;i<52;i++) { if(tree->next[i]!=NULL) del(tree->next[i]); } delete(tree); } int main() { int i,j,len,t1,t2,x,y; char str1[35],str2[35]; while(scanf("%d",&n)!=EOF&&n!=-1) { getchar(); for(i=1;i<=150;i++) for(j=1;j<=150;j++) { if(i==j) a[i][j]=0; else a[i][j]=100000000; visited[i]=1; } nima=1; root=new node; scanf("%s%s",str1,str2); x=build(str1); y=build(str2); while(n--) { scanf("%s%s%d",str1,str2,&len); if(x==y) continue; t1=build(str1); t2=build(str2); if(a[t1][t2]>len) a[t1][t2]=a[t2][t1]=len; getchar(); } n=nima-1; del(root); if(x==y) printf("%d\n",0); else dis(); } return 0; }
暴力+最短路实现:
#include<stdio.h> #include<string.h> int a[161][161],visited[161],num; char str[161][35]; int bijiao(char string[]) { int i; for(i=1;i<=num;i++) if(strcmp(str[i],string)==0) break; if(i==num+1) { num++; strcpy(str[num],string); return num; } else return i; } void dis() { int i,j,flag,min,depth[151]; for(i=2;i<=num;i++) depth[i]=a[1][i]; visited[1]=0; for(i=2;i<=num;i++) { min=100000000; flag=0;//开始的时候这里是没有的,然后是一直错 for(j=2;j<=num;j++) { if(visited[j]&&depth[j]<min) { min=depth[j]; flag=j; } } visited[flag]=0; if(flag==2) { printf("%d\n",min); break; } if(flag) for(j=2;j<=num;j++) { if(visited[j]&&depth[j]>(depth[flag]+a[flag][j])) depth[j]=depth[flag]+a[flag][j]; } } if(i==num+1) printf("-1\n"); } int main() { int n,i,j,S,E,len,t1,t2; char str1[35],str2[35]; while(scanf("%d",&n)!=EOF&&n!=-1) { getchar(); S=1; for(i=1;i<=160;i++) for(j=1;j<=160;j++) { if(i==j) a[i][j]=a[j][i]=0; else a[i][j]=a[j][i]=100000000; visited[i]=1; } num=1; scanf("%s%s",str1,str2); strcpy(str[1],str1); E=bijiao(str2); for(i=1;i<=n;i++) { scanf("%s%s%d",str1,str2,&len); if(S!=E) { t1=bijiao(str1); t2=bijiao(str2); if(a[t1][t2]>len) a[t1][t2]=a[t2][t1]=len; } getchar(); } if(S==E) printf("%d\n",0); else dis(); } return 0; }