UVa 10129 单词(DFS判断连通性)

题意:输入N个单词,N < 100000,是否可以把所有这些单词排成一列,使得每个单词的第一个字母和最后一个字母相同。每个单词最多有1000个字母,输入可能有重复的单词。

思路:
1、把字母当成结点,单词看做有向边,问题有解当且仅当图中存在欧拉回路。有向图判断存在欧拉回路的条件有两个:(1)把图看做无向图,图是连通的(DFS访问,若存在未访问的,则是不连通的) ;(2)最多有两个点入度不等于出度,其中一个是起点,一个是终点。

2、每行输入的数据只需记录首字母和最后一个字母,然后转化为数字,因此数组只需开到26记录26个字母对应的数字即可。

代码如下:

#include
#include
const int maxn = 1000 + 10;
int G[27][27],in[27],out[27],N,num[27];

void read() //读入数据
{
	memset(G,0,sizeof(G));
	memset(in,0,sizeof(in));
	memset(out,0,sizeof(out));
	scanf("%d",&N);
	char s[maxn];
	int first,last;
	while(N--)
	{
		scanf("%s",s);
		first = s[0] - 'a';
		last = s[strlen(s)-1] - 'a';
		G[first][last]++;
		in[last]++;
		out[first]++;
	}
	
}

void dfs(int i)
{
	num[i] = 1;
	for(int j = 0;j < 26;j++)
	{
		if((G[i][j] > 0 || G[j][i] > 0) && num[j] == 0)
		{
			dfs(j);
		}
	}
	return;
}

bool judge_connect() //判断连通性
{
	memset(num,0,sizeof(num));//存储访问情况
	for(int i = 0;i < 26;i++)
	{
		if(out[i] > 0)
		{
			dfs(i);
			break;
		}
	}
	
	for(int i = 0;i < 26;i++)
	{
		if((in[i] > 0 || out[i] > 0) && num[i] == 0)
		{
			return false;
		}
	}
	return true;	
}

bool judge_deg() //判断度数情况
{
	int i,start = 0,end = 0;
	for(i = 0;i < 26;i++)
	{
		if(in[i] != out[i])
		{
			if(in[i] == out[i] + 1)	end++;
			else if(out[i] = in[i] + 1) start++;
			else
			{
				return false;
			}
		}
		if(end > 1 || start > 1)
		{
			return false;
		}
	}
	if(start + end > 2) 
	{
		return false;
	}
	
	return true;
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		read();
		if(judge_connect() && judge_deg())
		{
			printf("Ordering is possible.\n");
		}
		else
		{
			printf("The door cannot be opened.\n");
		}
	}
} 

你可能感兴趣的:(UVAOJ那点可怜兮兮的进度,第6章)