注意:并查集必须初始祖先f[i]=i; !!!!
并查集判断树:
1. 空树,没有结点, 是树
2. 判断根节点个数,大于1不是树
3. 多个父结点,或已有关系
4. 编号不连续,要记录结点是否存在 vis[N]
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define N 100000
int f[N], flag, vis[N];
int getf(int x)
{
if (x == f[x])
return x;
else
{
f[x] = getf(f[x]);
return f[x];
}
}
void merge(int a, int b)
{
int x = getf(a);
int y = getf(b);
if (x != y)
f[b] = a;
}
int main()
{
int a, b, i;
int ans = 1;///输入组数
int cnt = 0;
memset(vis, 0, sizeof(vis));
for(i = 1; i <= N; i++)
f[i] = i;
flag = 0;
while(1)
{
scanf("%d %d", &a, &b);
if(a == -1 && b == -1)
break;
if (a == 0 && b == 0)
{
for(i = 1; i <= N; i++)
{
if(f[i] == i && vis[i])
cnt++;///树根个数
if (cnt > 1)
break;
}
if (flag || cnt > 1)///如果没有环 也不是森林
printf("Case %d is not a tree.\n", ans++);
else
printf("Case %d is a tree.\n", ans++);
memset(vis, 0, sizeof(vis));
for(i = 1; i <= N; i++)
f[i] = i;
flag = 0;
cnt = 0;
continue;
}
vis[a] = vis[b] = 1;
if (f[a] == f[b] || f[b] != b)///合并之前已在同一棵树上 或b结点已经有父亲
flag = 1;
merge(a, b);//合并
}
return 0;
}