10129 - Play on Words(*****)欧拉图,并查集

/*
有向欧拉图问题,刘汝佳p112页有详细说明
使用并查集来判断图是否连通,并判断入度和出度情况
题意:将门上的单词最后都拼接在一起,
其中前一个单词的最后一个字母必须和后一个单词的第一个字母相同
*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
const int nMax=30;
//degree
int indgr[nMax],outdgr[nMax],p[nMax];

int find(int x)
{
	return p[x]==x?x:p[x]=find(p[x]);
}

int main()
{
	//freopen("data.in","r",stdin);
	int T,N;
	scanf("%d",&T);
	while(T--)
	{
		memset(indgr,0,sizeof(indgr));
		memset(outdgr,0,sizeof(outdgr));
		for(int i=0;i<26;i++)
			p[i]=i;
		scanf("%d",&N);
		for(int i=0;i<N;i++)
		{
			string str;
			cin>>str;
			int a=str[0]-'a';
			int b=str[str.size()-1]-'a';
			indgr[b]++;
			outdgr[a]++;
			if(find(a)!=find(b))
				p[find(a)]=find(b);
		}
		bool ok=true;
		int u;
		for(u=0;!indgr[u] && !outdgr[u];u++);
		for(int i=u+1;i<26;i++)
			if((indgr[i] || outdgr[i]) && find(u)!=find(i))
			{
				ok=false;
				break;
			}
		if(ok)
		{
			int in_num=0,out_num=0;
			for(int i=0;i<26;i++)
			{
				if(indgr[i]>outdgr[i])
				{
					if(indgr[i]==outdgr[i]+1)
						in_num++;
					else
					{
						ok=false;
						break;
					}
				}
				else if(outdgr[i]>indgr[i])
				{
					if(outdgr[i]==indgr[i]+1)
						out_num++;
					else
					{
						ok=false;
						break;
					}
				}
			}
			if(in_num>1 || out_num>1)//在这里WA了N多次,出错原因,漏掉了in_num和out_num都为零的那种情况
				ok=false;
		}
		if(ok)
			printf("Ordering is possible.\n");
		else
			printf("The door cannot be opened.\n");
	}
	return 0;
}


你可能感兴趣的:(10129 - Play on Words(*****)欧拉图,并查集)