pku 1386 ,hdu 1116 Play on Words

和poj的2513差不多,不过没那么麻烦,这个不需要用Trie树。。

并查集+欧拉回路。

先看成是一个无向图,判断连通性。 之后记录每一个字母的入度和出度。

这个也是两种情况:

一种:所有点的入度==其出度;

另一种:只有两个点的入度不等于它的出度, 并且其中一个点的入度==其出度+1,另一个点的出度==其入度+1;

这样就很简单了^_^

# include<stdio.h>

# include<string.h>

# define MAX 27

int father[MAX],indegree[MAX],outdegree[MAX];

int find(int x)

{

	while(father[x]!=x)

		x=father[x];

	return x;

}

void Union(int a,int b)

{

	int x,y,min;

	x=find(a);

	y=find(b);

	min=x<y?x:y;

	father[a]=father[b]=father[x]=father[y]=min;

}

int main()

{

	int ncase,i,j,n,ans1,ans2,len,count1,flag,count2;

	char str[1005];

	scanf("%d",&ncase);

	while(ncase--)

	{

		for(i=0;i<MAX;i++)

		{

			father[i]=i;

			indegree[i]=0;

			outdegree[i]=0;

		}

		scanf("%d",&n);

		while(n--)

		{

			scanf("%s",str);

			len=strlen(str);

			ans1=str[0]-'a';

			ans2=str[len-1]-'a';

			outdegree[ans1]++;

			indegree[ans2]++;

			Union(ans1,ans2);

		}

		for(i=0;i<26;i++)

			if(indegree[i]!=0 || outdegree[i]!=0) break;//找到出现的字母中最小的一个

		flag=0;

		count1=0;//

		count2=0;

		for(j=i;j<26;j++)

		{

			if(outdegree[j]==0 && indegree[j]==0) continue;///不考虑未出现的字母

			if(find(j)!=i) {flag=1;break;}//判断是否连通

			if(indegree[j]!=outdegree[j])

			{

				if(outdegree[j]==indegree[j]+1) count1++;//出度比入度大的点

				else if(indegree[j]==outdegree[j]+1) count2++;//入度比出度大的点

				else {flag=1;break;}//如果入度、出度相差不只是1,则不能打开门

			}

			if(count1>=2 || count2>=2) {flag=1;break;}

		}

		if(flag==1) printf("The door cannot be opened.\n");

		else printf("Ordering is possible.\n");

	}

	return 0;

}



你可能感兴趣的:(word)