例题6-16 UVa10129 Play on Words(欧拉回路)

题意:

输入一些单词,看是否能将这些单词首尾分别对应相同的排成一个序列

要点:

欧拉道路,也即是从无向图的一个结点出发走出一条道路,每条边恰好经过一次,俗称一笔画,

对于无向图来说:如果一个无向图是连通的(任意一个点出发,通过dfs遍历可得到所以顶点),且最多只有两个度数为奇数的顶点,则一定存在欧拉道路。如果有两个奇点,一定从一个奇点出发一个奇点结束;如果奇点不存在,则可以从任意点出发,一定可以回到该点(称为欧拉回路)

对于有向图来说:最多两个点的入度不等于出度,一个出度比入度大一(起点),一个入度比出度大一(终点),并且它的底图(对应的无向图)必须连通

判断连通的方法有两种:1.DFS,2.并查集(不会)


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int g[30][30],visit[30][30];
int cnt;

void dfs(int current)
{
	cnt++;
	for (int j = 0; j < 26; j++)
	{
		int sum = g[current][j];		//头尾分别相同的字符串可以有好几个
		int num = visit[current][j];	//记录访问的次数
		if (sum > 0 && num < sum)		//只要访问次数小于同一条边的数目即可
		{
			visit[current][j]++;
			dfs(j);
		}
	}
}

int main()
{
	int t,i,j,n;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d", &n);
		getchar();
		memset(g, 0, sizeof(g));
		memset(visit, 0, sizeof(visit));
		char str[1050];
		for (i = 0; i < n; i++)
		{
			scanf("%s", str);
			int num = strlen(str) - 1;
			g[str[0] - 'a'][str[num] - 'a'] ++;//记录首尾的字符对应下标
		}
		bool flag = false;
		for (i = 0; i < 26; i++)
		{
			for (j = 0; j < 26; j++)
			{
				if (g[i][j]>0)
				{
					cnt = 0;
					visit[i][j]++;//最开始的边先录进去,先确定起点
					dfs(j);
					if (cnt == n) { flag = true; goto loop; }//适当的使用goto可以跳出多重循环
					memset(visit, 0, sizeof(visit));
				}
			}
		}
		loop:
		if (flag)
			printf("Ordering is possible.\n");
		else
			printf("The door cannot be opened.\n");
	}
	return 0;
}



posted @ 2016-02-20 22:13  seasonal  阅读(113)  评论(0编辑  收藏  举报