poj2337Catenyms(有向欧拉图:输出欧拉路径)

题意给你一组N个单词,现在要你输出这样一组单词序列。该序列包含了所有N个单词,且该序列中的前一个单词的最后一个字母与后一个单词的第一个字母相同。如果存在多个这种首尾相连的序列,就输出字典序最小的那个即可。

思路首先我们把每个单词看成一条边,把每个单词的首尾两个小写字母看成节点(不一定存在所有26个节点),其实就是在找一条欧拉路径。麻烦的是这道题目并没有告诉一定存在欧拉路,所以还需要判断是否存在


#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
using namespace std;
#define maxn 1000+10
#define LL long long
int cas=1,T;
struct word
{
	int len;
	char s[50];
	bool operator < (const word &rhs)const
	{
		return strcmp(s,rhs.s)<0;
	}
}words[maxn];
struct Edge
{
	int u,v;
	bool vis;
}edges[maxn];
int pre[maxn];
int in[maxn];
int out[maxn];
int mark[maxn];
int m;
int cnt,ans[maxn];
int Find(int x)
{
	return pre[x]==-1?x:pre[x]=Find(pre[x]);
}
bool check()
{
	int k = 0;
	for (int i = 0;i<26;i++)
		if (mark[i])
		if (Find(i)==i)
			k++;
	return k==1;
	/**if (k==1)
		return true;
	else
		return false;*/
}
void euler(int u)
{
	for (int i = 0;i<m;i++)
		if (!edges[i].vis && edges[i].u==u)
		{
			edges[i].vis=1;
			euler(edges[i].v);
			ans[cnt++]=i;
		}
}
int main()
{
	//freopen("in","r",stdin);
	scanf("%d",&T);
	while (T--)
	{
		scanf("%d",&m);
		for (int i = 0;i<m;i++)
		{
			scanf("%s",words[i].s);
			words[i].len = strlen(words[i].s);
		}
		sort(words,words+m);
		memset(pre,-1,sizeof(pre));
		memset(mark,0,sizeof(mark));
		memset(in,0,sizeof(in));
		memset(out,0,sizeof(out));
		for (int i = 0;i<m;i++)
		{
			int u,v;
			u=words[i].s[0]-'a';
			v=words[i].s[words[i].len-1]-'a';
			edges[i].u=u;
			edges[i].v=v;
			edges[i].vis=0;
			in[v]++;
			out[u]++;
			mark[u]=mark[v]=1;
			u=Find(u);
			v=Find(v);
			if (u!=v)
				pre[u]=v;
		}
		int start=edges[0].u;
		int i,c1=0,c2=0;
		for (i = 0;i<26;i++)
		{
			if (mark[i])
			{
			  if (in[i]==out[i])continue;
			  else if (in[i]-out[i]==1) c1++;
			  else if (out[i]-in[i]==1) c2++,start=i;
			  else break;
			}
		}
		if (i==26 && ((c1==c2&&c1==0) || (c1==c2&&c1==1)) && check())
		{
			cnt=0;
            euler(start);
			printf("%s",words[ans[cnt-1]].s);
			for (int i = cnt-2;i>=0;i--)
			{
				printf(".%s",words[ans[i]].s);
			}
			printf("\n");
		}
		else
			printf("***\n");
	}
	//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
	return 0;
}


题目

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
***


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值