Is It A Tree? (并查集)

 

 思路:搞人的题,特判0 0 的时候 输出    "is a tree.",

存在回路的时候 输出   "is not  a tree.",

存在两个联通分量的时候输出   "is not  a tree."。也就是两个树的时候。

两个树要怎么判断呢

假设给出的所有的边,组成一棵树,利用并查集我们可以把他所有的子节点并到一个节点上,所以我们只要判断有多少节点的父亲是他本身就行了。如果大于1,就证明存在两个树(注意一点,不一定所有的点都压缩到极致,也就是所有的点都挂在一个节点上,他可能是间接的挂在这个根节点上)

就例如下面的运行结果。

 

 有的点是间接和根节点4相连接的,但是我们发现根节点4的父亲是他本身,所以我们只要判断有多少节点的父节点是他本身就行了,如果超过一个就说明存在两个树,否则就是一棵树。

#include <iostream>
using namespace std;
int a,b,n;
int pre[1000005];
int flage;
int vis[1000005];  //标记数组,节点可能不是从1~n,所有要标记一下哪几个点出现过。
int cnt;
int root( int x ){
    if ( x!=pre[x] ) {
        pre[x] = root(pre[x]);
    }
    return pre[x];
}
void join( int a, int b ){
    int x = root(a);
    int y = root(b);
    if ( x==y ) {
        flage = 0;  //表示出现环。
    }
    else {
        pre[x] = y;
    }
}
int main()
{
    int s = 1;
    while ( cin>>a>>b && a!=-1 && b!=-1 ) {
        if ( a==-1 && b==-1 ) {
            break ;
        }
        for ( int i=0; i<=100002; i++ ) {
            pre[i] = i;
            vis[i]=0;
        }
        cnt = 0;
        flage = 1;
        n = 0;
        join(a,b);
        vis[a]=1;
        vis[b]=1;
        if ( a==0 && b==0 ) {
            cout << "Case " << s++ << " is a tree." << endl;
            continue ;
        }
        while ( cin>>a>>b && a!=0 && b!=0 ) {
            join(a,b);
            vis[a]=1;
            vis[b]=1;
        }
        if(flage==0){
         cout << "Case " << s++ << " is not a tree." << endl;
         continue;
        }
        int cntt = 0;
        for ( int i=0; i<100002; i++ ) {
            /*if(vis[i]==1)
            {
            cout<<"i  "<<i<<" pre[i] "<<pre[i]<<endl;
            }*/
            if (pre[i]==i&&vis[i]==1) {
                cnt++;                     //判断有几棵树
            }
        }
        if ( cnt==1) {
            cout << "Case " << s++ << " is a tree." << endl;
        }
        else {
            cout << "Case " << s++ << " is not a tree." << endl;
        }
    }
    return 0;
}
View Code

 

posted @ 2020-10-21 18:48  Swelsh-corgi  阅读(156)  评论(0编辑  收藏  举报