SP41 WORDS1

秘密的门里藏着一些字谜。一些考古学家希望打开这些门,因此他们需要解开这些字谜。由于没有任何其他方式(不要总想着暴力!)可以打开这扇门,这个字谜对我们来说尤其重要。 每一扇门上都有很多磁性的盘子,每一个盘子上面都写着一个单词。这些盘子必须要按照一种特殊的顺序排列,即除了第一个单词以外的每一个单词的首字母必须是前面一个单词的结尾字母。你的任务就是编写一个程序,测试给出的单词能否按照要求的顺序排列并且顺利地打开这扇门。
对每一个单词从首字母连一条到尾字母的有向边,然后判断是不是欧拉路径。

Code

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int t,n,in[50],to[50],cnt,vis[50],f[50];
char ch[2000];
vector <int> a[50];
void clear()
{
	for (int i=1;i<=26;i++)
		vis[i]=f[i]=in[i]=to[i]=0,a[i].clear();
}
int bfs(int st)       //bfs判断基图是否连通
{
	queue <int> q;
	q.push(st);
	vector <int>::iterator it;
	vis[st]=1;
	int num=1;
	while (!q.empty())
	{
		int u=q.front();q.pop();
		for (it=a[u].begin();it!=a[u].end();it++)
		{
			int v=(*it);
			if (!vis[v])
				q.push(v),vis[v]=1,num++;
		}
	}
	int x=0;
	for (int i=1;i<=26;i++)
		if (f[i])
			x++;
	if (num==x)
		return 1;
	return 0;
}
int main()
{
	cin>>t;
	while (t--)
	{
		clear();
		cin>>n;
		int fl1=0,fl2=0,fl3=0,st=0;
		for (int i=1;i<=n;i++)
		{
			scanf("%s",ch+1);
			int l=strlen(ch+1),u=ch[1]-'a'+1,v=ch[l]-'a'+1;
			a[u].push_back(v);
			a[v].push_back(u);
			to[u]++;     //出度
			in[v]++;     //入度
			f[u]=1;
			f[v]=1;
			st=u;       //bfs时随便的一个起点
		}
		for (int i=1;i<=26;i++)
			if (in[i]==to[i])
				fl3++;
			else
				if (in[i]==to[i]+1)
					fl1++;
				else
					if (in[i]+1==to[i])
						fl2++;
		if ((fl3==24&&fl1&&fl2||fl3==26)&&bfs(st))  //判断欧拉路径
			cout<<"Ordering is possible."<<endl;
		else
			cout<<"The door cannot be opened."<<endl;
	}
	return 0;
}
~~~
原文地址:https://www.cnblogs.com/sdlang/p/13068096.html