我的个人博客:地址
HDU1878——欧拉回路(并查集)
http://acm.hdu.edu.cn/showproblem.php?pid=1878题意:这道题讲的是判断是否是一个欧拉回路。
欧拉回路: 通过图中每条边且只通过一次,并且经过每一顶点的回路。
无向图是否具有欧拉通路或回路的判定:
欧拉通路:图连通;图中只有0个或2个度为奇数的节点
欧拉回路:图连通;图中所有节点度均为偶数
有向图是否具有欧拉通路或回路的判定:
欧拉通路:图连通;除2个端点外其余节点入度=出度;1个端点入度比出度大1;一个端点入度比出度小1 或 所有节点入度等于出度
欧拉回路:图连通;所有节点入度等于出度
这道题的算法思路:利用并查集先判断图连通性,然后利用in数组记录各点的度。(因为该题是无向图)
判断条件:当一个点的根节点与其他点的根节点不等,则不连通,则返回0;当该点的度数是奇数时则非欧拉图,返回0;其他情况返回1
#include<cstring>
#include<iostream>
#include<cstdio>
#define For(i, n) for(int i = 0; i < n; i++)
using namespace std;
const int MAXN = 30;
int fa[MAXN], vis[MAXN], in[MAXN], out[MAXN];
void Init() // 初始化
{
For(i, 26) { fa[i] = i, vis[i] = in[i] = out[i] = 0; }
}
int Find(int x) //找老大
{
int r = x;
while(fa[r] != r) {
r = fa[r];
}
return r;
}
void Union(int x, int y) //合并
{
int fx = Find(x);
int fy = Find(y);
if(fx != fy)
fa[fx] = fy;
}
int main()
{
int t, n, x, y;
char str[1000 + 10];
bool flag;
cin >> t;
while(t--) {
Init();
cin >> n;
For(i, n) {
scanf("%s", str);
x = str[0] - 'a';
y = str[strlen(str) - 1] - 'a';
Union(x, y);
out[x]++;
in[y]++;
vis[x] = vis[y] = 1;
}
int r = 0;
For(i, 26) { if(vis[i] && fa[i] == i) r++; }
if(r > 1) flag = false;
else {
int n1 = 0;
int n2 = 0;
For(i, 26) {
if(in[i] != out[i] && vis[i]) {
if(in[i] - out[i] == 1)
n1++;
else if(out[i] - in[i] == 1)
n2++;
else n1 = 3; //判断第三种情况,两个单词相同(OK,OK)
}
}
if( (n1 == 0 && n2 == 0) || (n1 == 1 && n2 == 1) )
flag = true;
else flag = false;
}
if(flag) cout << "Ordering is possible." << endl;
else cout <<"The door cannot be opened." << endl;
}
return 0;
}