例题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;
}