看了以前的提示才写出来的,判断连通用了dfs(并查集是什么?)
对于欧拉回路:
首先判断:是否存在一条路径,使得我从一个结点出发, 每条边恰好走过一次(or给定的次数)?
1、首先,图中所有点是连通的 (dfs,并查集)
2、奇点?
(1)无向图:除了起点和终点,其他点的进出次数必须相等。
(2)最多有两个点的入度不等于出度,而且必须是其中一个点的出度比入度恰好大1(起点),另一个的入度比出度大1(终点)。
第一点往往在第二点后判断,在判断第二点时找到欧拉回路的起点,用dfs从起点开始走出欧拉回路(但为什么从起点开始走出来的线路就是欧拉回路?),如果有点没有被访问到,说明图不连通。
其实不需要用set记录那些结点是不是在图里面的,由于每条边必须走过给定的次数,所以如果dfs后有graph[u][v]不为0,就不行了
#include<stdio.h>
#include<string.h>
const int max_input = 1000 + 10;
const int maxn = 30;
char input[max_input];
int graph[maxn][maxn];
int in[maxn];
int out[maxn];
int set[maxn]; //
int visited[maxn]; //
void dfs(int u)
{
for(int v = 0; v < maxn; ++v)
{
if(graph[u][v] > 0)
{
--graph[u][v];
dfs(v);
visited[v] = 1;
}
}
}
int main()
{
//
freopen("input.txt", "r", stdin);
int T, N;
scanf("%d", &T);
for(int k = 0; k < T; ++k)
{
scanf("%d", &N);
memset(graph, 0, sizeof(graph));
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(set, 0, sizeof(set)); //which of the 'a' to 'z' is in the graph
int min = 30;
for(int i = 0; i < N; ++i)
{
scanf("%s", input);
int n1, n2;
n1 = input[0] - 'a', n2 = input[strlen(input)-1] - 'a';
graph[n1][n2]++;
out[n1]++, in[n2]++;
set[n1] = set[n2] = 1;
min = n1 < min? n1: min;
min = n2 < min? n2: min;
}
bool ok = true;
int cnt1 = 0, cnt2 = 0;
int rcs_start = min;
for(int i = 0; i < maxn; ++i)
{
if(in[i] == out[i])
continue;
else if(out[i] == in[i]+1)
{
cnt1++;
rcs_start = i;
}
else if(in[i] == out[i]+1)
cnt2++;
else
{
ok = false;
break;
}
}
if(!((cnt1 == 0 && cnt2 ==0) || (cnt1==1 && cnt2 ==1)))
ok = false;
//connected?
memset(visited, 0, sizeof(visited));
visited[rcs_start] = 1;
dfs(rcs_start);
for(int i = 0; i < maxn; ++i)
{
if(set[i] && !visited[i])
{
ok = false;
break;
}
}
if(ok)
puts("Ordering is possible.");
else
puts("The door cannot be opened.");
}
}