poj 2337-Catenyms

Catenyms
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 9832 Accepted: 2561

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
***
代码:

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
int degreein[26],degreeout[26],d[1005];
bool visit[1005];
struct deg{
	int start;
	int end;
	char w[30];
}deg_order[1005];
int num;
int cmp(const void *a,const void *b)
{
	deg *c=(deg *)a;
	deg *d=(deg *)b;
	if(c->start!=d->start)
		return c->start-d->start;
	else
		return strcmp(c->w,d->w);
	
}
int Abs(int a)
{
	if(a>0)
		return a;
	else
		return -a;
}
int getsource()//寻找起点
{
	int i;
	int source,cnt1=0,cnt2=0;
	for(i=0;i<26;i++)
	{
		if(Abs(degreein[i]-degreeout[i])==2)
			return -1;
		else 
			if(degreein[i]-degreeout[i]==1)
			{
				cnt1++;//基度顶点加1
			}
			else 
				if(degreein[i]-degreeout[i]==-1)
				{
					cnt2++;//基度顶点加1
					source=i;
				}
	}
	if(cnt1>1||cnt2>1)//如果基度顶点数大于一说明不能构成欧拉路径
		return -1;
	if(cnt1==0)//如果不存在基度顶点
	{
		int i;
		for(i=0;i<26;i++)
			if(degreeout[i])
				return i;
	}
	else     //找到起始点
		return source;
}

bool dfs(int source,int cnt)//搜索是否存在欧拉路径
{
	int i;
	if(cnt==num)
		return true;
	for(i=0;i<num;i++)
	{
		if(visit[i]||deg_order[i].start<source)
			continue;
		else
			if(deg_order[i].start>source)
				return false;
			d[cnt]=i;
			visit[i]=1;
			
			if(dfs(deg_order[i].end,cnt+1))
				return true;
			visit[i]=0;
			
	}
	return false;
}






int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(visit,0,sizeof(visit));
		memset(degreein,0,sizeof(degreein));
		memset(degreeout,0,sizeof(degreeout));
		cin>>num;
		int i;
		for(i=0;i<num;i++)
		{
			cin>>deg_order[i].w;
			deg_order[i].start=deg_order[i].w[0]-'a';
			deg_order[i].end=deg_order[i].w[strlen(deg_order[i].w)-1]-'a';
			degreein[deg_order[i].end]++;
			degreeout[deg_order[i].start]++;
		}
		int source=getsource();
		if(source==-1)
		{
			cout<<"***"<<endl;
			continue;
		}
		qsort(deg_order,num,sizeof(deg_order[0]),cmp);
		if(!dfs(source,0))
		{
            cout<<"***"<<endl;
			continue;
		}
		int j;
		cout<<deg_order[d[0]].w;
		for(j=1;j<num;j++)
			cout<<'.'<<deg_order[d[j]].w;
		cout<<endl;
	}
	return 0;
}




 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值