求欧拉通路。。。
用深搜就好了,毕竟只会有一个桥,一般情况下不回回溯很多的。
因为这题跟首字母关系很大,所以把每个串按首字母分类了。
然后把首字母里的串排序就好了。。
我排的是倒序,刚开始觉得倒序的话边可以容易退出。。
但其实完全不是这样,因为用深搜写的,有可能回溯回来寻找其它的边了,而最小的串可能以后用。
写了两天 把所有能犯的错误都犯到了
dfs写错n次不说什么了。。
写了数据以后进行强大的推理论证,最后发现在很奇葩的位置,初始化写错了。
判连通要判基图连通性,也就是无向图的啊。。。
判是否访问过某个点不仅要看入度还要看出度啊。。。
深搜的时候不要用过了一条边就top--啊,有可能回溯回来用的是第2条边啊。。
深搜的退出条件还是永远都掌握不好啊。。。
另外炫耀下找欧拉通路和回路时候的判断。。翔见代码吧。。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<vector> using namespace std; vector<string>e[30],as; int g[30],x,flag,n,cnt; int f[30][1010],v[30][1010]; int d[30],t[30],p[30][30]; void dfs(int a){ if(x==n){flag=1;return ;} int i,c; for(i=g[a]-1;i>=0;i--){//按从小到大寻找可行路径 c=v[a][i]; if(!f[a][i]){//以a开头第i个串是否可行(没被用过) x++;f[a][i]=1; dfs(c); x--;f[a][i]=0; } if(flag)break; } if(flag)as.push_back(e[a][i]); } void tong(int a){//判连通 int i;t[a]=1; for(i=0;i<26;i++) if(!t[i]&&p[a][i]) tong(i); } int main(){ int i,j,cs,c,b; char s[50]; string str; scanf("%d",&cs); while(cs--){ scanf("%d",&n); as.clear(); for(i=0;i<30;i++){ for(j=0;j<1010;j++) f[i][j]=v[i][j]=0; for(j=0;j<30;j++) p[i][j]=0; e[i].clear(); g[i]=d[i]=t[i]=0;//入度,出度,连通标记 } for(i=0;i<n;i++){//按首字母分类 scanf("%s",s); str=s; c=s[0]-'a'; e[c].push_back(str); g[c]++; } for(i=0;i<26;i++){//将各首字母类里的串排序 sort(e[i].begin(),e[i].end()); reverse(e[i].begin(),e[i].end()); } for(i=0;i<26;i++) for(j=0;j<g[i];j++){ c=e[i][j].length(); b=e[i][j][c-1]-'a';//取尾字母 c=e[i][j][0]-'a';//取首字母 p[b][c]=p[c][b]=1;//基图邻接矩阵 v[i][j]=b;//以i开头,从大到小第j个串的尾字母是b d[b]++;//出度 } for(i=0;i<26;i++)if(g[i]){//判连通 tong(i);break; } for(i=0;i<26;i++)if((g[i]||d[i])&&!t[i])break; if(i<26){cout<<"***"<<endl;continue;} c=b=100;flag=0;x=0;//c尾,b头,flag找到路径,x深度 for(j=i=0;i<26;i++) if(d[i]!=g[i]){ if(d[i]-g[i]==1)c=i; else if(d[i]-g[i]==-1)b=i; else flag=1; j++; } if(j==2&&c+b<100&&!flag){//找欧拉路 dfs(b); reverse(as.begin(),as.end()); for(i=0;i<n-1;i++)cout<<as[i]<<"."; cout<<as[n-1]<<endl; } else if(j==0&&!flag){//找欧拉回路 for(i=0;i<26&&!flag;i++,x=0)if(g[i])dfs(i); reverse(as.begin(),as.end()); for(i=0;i<n-1;i++)cout<<as[i]<<"."; cout<<as[n-1]<<endl; } else cout<<"***"<<endl; } return 0; }