hdu1272
小希的迷宫
0x00 Tags
并查集
0x01 题目简介
- 并查集产生的每一个集合都是一棵树
- 流程:初始化;查找–判断两个元素是否在一个集合;合并
- 查找过程递归可能会爆栈,采用递归方式进行路径压缩
- 用并查集判断是否有环;对同一个集合来说只存在一个根节点
- 合并的过程是一个建树的过程,当合并失效时,说明两个节点在同一个集合中,这两点连的边成环
- 使用isroot数组记录有几个根节点–有几个不同的集合
判断是否连通:顶点数==边数+1
0x02 代码
代码—与上面思想相同
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int root[maxn];
// 成环标志
bool circle;
void Init()
{
for (int i = 1; i < maxn; i++)
{
root[i] = i;
}
}
int Find(int x)
{
//return x == root[x] ? x : Find(root[x]);
while (x != root[x])
{
x = root[x];
}
return x;
}
void Union(int x, int y)
{
x = Find(x);
y = Find(y);
if (x != y) root[x] = y;
else circle = 0; // 成环
}
int main()
{
set<int> v; // 记录顶点
int a, b, sum; // sum记录边数
while (scanf("%d%d",&a,&b) != EOF)
{
if (a == -1 && b == -1) break;
if (a == 0 && b == 0)
{
printf("Yes
");
continue;
}
Init();
sum = 1;
circle = false;
v.insert(a);
v.insert(b);
if (!circle)
Union(a, b);
while (1)
{
scanf("%d%d", &a, &b);
if (a == 0 && b == 0) break;
v.insert(a);
v.insert(b);
if (!circle) Union(a, b);
sum++;
}
/*
while (scanf("%d%d", &a, &b) != EOF)
{
if (a == 0 && b == 0) break;
v.insert(a);
v.insert(b);
if (!circle) Union(a, b);
sum++;
}
*/
if (!circle && v.size() == sum + 1)
printf("Yes
");
else
printf("No
");
v.clear();
}
return 0;
}
代码二
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int root[maxn], sign[maxn];
// 成环标志
int flag;
void Init()
{
for (int i = 1; i < maxn; i++)
{
root[i] = i;
sign[i] = 0;
}
}
int Find(int x)
{
//return x == root[x] ? x : Find(root[x]);
while (x != root[x])
{
x = root[x];
}
return x;
}
void Union(int x, int y)
{
x = Find(x);
y = Find(y);
if (x != y) root[x] = y;
else flag = 0;
}
int main()
{
int a, b;
while (scanf("%d%d",&a,&b) != EOF)
{
if (a == -1 && b == -1) break;
if (a == 0 && b == 0)
{
printf("Yes
");
continue;
}
Init();
sign[a] = sign[b] = 1;
flag = 1;
Union(a, b);
while (scanf("%d%d", &a, &b) != EOF)
{
if (a == 0 && b == 0) break;
Union(a, b);
sign[a] = sign[b] = 1;
}
int k = 0;
for (int i = 1; i < maxn; i++)
{
if (sign[i] && root[i] == i) // 判断根节点数目
k++;
if (k > 1) flag = 0;
}
if (flag) printf("Yes
");
else printf("No
");
}
return 0;
}