poj--2337(输出欧拉路径)

Catenyms
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 10681 Accepted: 2788

Description

A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For example, the following are catenyms: 
dog.gopher

gopher.rat

rat.tiger

aloha.aloha

arachnid.dog

A compound catenym is a sequence of three or more words separated by periods such that each adjacent pair of words forms a catenym. For example, 

aloha.aloha.arachnid.dog.gopher.rat.tiger 

Given a dictionary of lower case words, you are to find a compound catenym that contains each of the words exactly once.

Input

The first line of standard input contains t, the number of test cases. Each test case begins with 3 <= n <= 1000 - the number of words in the dictionary. n distinct dictionary words follow; each word is a string of between 1 and 20 lowercase letters on a line by itself.

Output

For each test case, output a line giving the lexicographically least compound catenym that contains each dictionary word exactly once. Output "***" if there is no solution.

Sample Input

2
6
aloha
arachnid
dog
gopher
rat
tiger
3
oak
maple
elm

Sample Output

aloha.arachnid.dog.gopher.rat.tiger

***

解体思路:WA了无数遍终于ac了.主要是要理解如何寻找欧拉回路--套圈法.附上网上对这种方法的解释:对于欧拉图,从一个节点出发,随便往下走(走过之后需要标记一下,下次就不要来了),必然也在这个节点终止(因为除了起始节点,其他节点的度数都是偶数,只要能进去就能出来)。这样就构成了一个圈,但因为是随便走的,所以可能会有些边还没走过就回来了。我们就从终止节点逆着往前查找,直到找到第一个分叉路口,然后从这个节点出发继续上面的步骤,肯定也是可以找到一条回到这个点的路径的,这时我们把两个圈连在一起。当你把所有的圈都找出来后,整个欧拉回路的寻找就完成了。

代码如下:

#include<stdio.h>
#include<string.h>
#include<stack>
#include<algorithm>
using namespace std;
stack<int>S;
struct stu{
	char s[25];
	int t,ne;
};
stu edge[1010];
int path[1010];
int vist[1010];
int exist[30];
int id[30];
int od[30];
int head[30];
int num;
int cmp(stu a,stu b){
	return strcmp(a.s,b.s)>0;
}
void dfs(int x){
	for(int i=head[x];i!=-1;i=edge[i].ne){
		if(!vist[i]){
			vist[i]=1;
			dfs(edge[i].t);
			path[num++]=i;
		}
	}
}
int main(){
	int t,n,star;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i=0;i<n;i++){
			scanf("%s",edge[i].s);
		}
		sort(edge,edge+n,cmp);
		memset(exist,0,sizeof(exist));
		memset(id,0,sizeof(id));
		memset(od,0,sizeof(od));
        memset(head,-1,sizeof(head));
        memset(vist,0,sizeof(vist));
		star=30;
		for(int i=0;i<n;i++){
			int l=strlen(edge[i].s);
			int x=edge[i].s[0]-'a';
			int y=edge[i].s[l-1]-'a';
			//edge[i].f=x;
			edge[i].t=y;
			//edge[i].id=i;
			edge[i].ne=head[x];
			head[x]=i;
			exist[x]=1;
			exist[y]=1;
			od[x]++;
			id[y]++;
			if(x<star)star=x;
			if(y<star)star=y;
		}
//		for(int i=0;i<n;i++)
//		printf("%s\n",edge[i].s);
		int sum=0;
		int ans=0;
		int a1=0;
		int a2=0;
		for(int i=0;i<30;i++){
			if(exist[i]){
				ans++;
				if(id[i]==od[i]){
					sum++;
				}
				if(id[i]-od[i]==1){
				       a1=1;	
				}
				if(od[i]-id[i]==1){
					a2=1;
					star=i;
				}
			}
		}
		if(sum==ans||(sum==ans-2&&a1&&a2)){
		    num=0;
			dfs(star);
			if(num!=n){
				printf("***\n");
			}
			else{
				printf("%s",edge[path[num-1]].s);
				for(int i=num-2;i>=0;i--){
					printf(".%s",edge[path[i]].s);
				}
				printf("\n");
			}
		}
		else printf("***\n");
	}
	return 0;
}       

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值