并查集之树-----Is It A Tree?

注意:并查集必须初始祖先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;
}


发布了29 篇原创文章 · 获赞 4 · 访问量 4703

猜你喜欢

转载自blog.csdn.net/onion___/article/details/79136589