POJ 2337 Catenyms

求欧拉通路。。。

用深搜就好了,毕竟只会有一个桥,一般情况下不回回溯很多的。

因为这题跟首字母关系很大,所以把每个串按首字母分类了。

然后把首字母里的串排序就好了。。

我排的是倒序,刚开始觉得倒序的话边可以容易退出。。

但其实完全不是这样,因为用深搜写的,有可能回溯回来寻找其它的边了,而最小的串可能以后用。

 

写了两天 把所有能犯的错误都犯到了

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;
}


 

你可能感兴趣的:(POJ 2337 Catenyms)