Is It A Tree?——简单并查集应用

Posted j666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Is It A Tree?——简单并查集应用相关的知识,希望对你有一定的参考价值。

题目链接

题意:

判断所给的数据能否构成一颗树。

题解:

题目中所给的是有向树,并给出了性质:
1.只有一个节点,称为根节点,没有定向边指向它。
2.除了根节点外,每个节点都只有有一条指向它的边。
3.从树根到任一结点有一条有向通路。
抽象过来就是三个条件:
1.只有一个入度为0的点,作为根节点。
2.除根节点外,其他点的入度只能为1。
3.所有点都能连通,也就是所有点需要在一个集合中,使用并查集来划分集合。

注意!!!可能会出现空树,也就是0 0,空树也是树。

代码:

技术图片
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 2e5+7;
int f[maxn],d[maxn],vis[maxn],in[maxn];
int a,b;
int Find(int x)

    return f[x]==x?x:f[x]=Find(f[x]);

void join(int x,int y)

    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy)
    
        f[fy]=fx;
    

int main()


    int Case=1;
    while(~scanf("%d%d",&a,&b))
    
        if(a==-1 && b==-1)break;
        for(int i=0; i<maxn; i++)f[i]=i,in[i]=0,vis[i]=0;
        if(a==0 && b==0)
        
            printf("Case %d is a tree.\n",Case++);
            continue;
        
        vis[a]=1;
        vis[b]=1;
        in[b]++;
        join(a,b);
        while(~scanf("%d%d",&a,&b))
        
            if(a==0 && b==0)break;
            vis[a]=1;
            vis[b]=1;
            in[b]++;
            join(a,b);

        
        int flag=1;
        int root=0;
        int cnt=0;
        for(int i=1;i<maxn;i++)
        
            if(vis[i] && in[i]==0)root++;///根节点个数 
            if(in[i]>=2)flag=0;///除了根节点外,其他点入度为1 
            if(vis[i] && f[i]==i)cnt++;///判断所有点是否都在一个集合 
        
        if(root!=1 || cnt>1)flag=0;

        if(flag)printf("Case %d is a tree.\n",Case++);
        else printf("Case %d is not a tree.\n",Case++);

    

    return 0;
View Code

 

以上是关于Is It A Tree?——简单并查集应用的主要内容,如果未能解决你的问题,请参考以下文章

Is It A Tree? (并查集)

HDU-1325-Is It A Tree?(并查集)

POJ - 1308 Is It A Tree?并查集

POJ 1308 Is It A Tree? [并查集]

HDU 1325 POJ 1308 Is It A Tree? (并查集)

POJ-1308 Is It A Tree?(并查集判断是否是树)