HDU 1272 小希的迷宫 并查集

题意
给出一个图,问这个图是否是一棵树
思路
首先判断这个图有没有环,这个直接用并查集就可以判断,为此我改进了并查集的模板,然后就是判断这个图是不是一片森林,这个需要记录下有多少个点,如果有n个点,有n-1条边就是一棵树
传送门

http://acm.hdu.edu.cn/showproblem.php?pid=1272

Code
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

class UnionFind {
private:
    int * fa;
    int size;
public: 
    UnionFind(int n) {
        size = n;
        fa = new int[n+1];
        Init();
    }

    ~UnionFind() {
        delete[] fa;
    }

    void Init() {
        for(int i = 1 ; i <= size ; i ++) {
            fa[i] = i;
        }
    }

    int Find(int x) {
        if(fa[x] != x) {
            fa[x] = Find(fa[x]);
        }
        return fa[x];
    }

    bool Union(int x,int y) {
        int fx = Find(x);
        int fy = Find(y);
        if(fx != fy) {
            fa[fx] = fy;
            return true;
        }
        else {
            return false;
        }
    }

    int GetCount() {
        int count = 0;
        for(int i = 1 ; i <= size ; i ++) {
            if(fa[i] == i) {
                count ++;
            }
        }
        return count;
    }
};

const int maxn = 100000;

bool vis[maxn+1];

int main() {
    int u,v;
    bool ret;
    UnionFind uf(maxn);
    while(scanf("%d %d",&u,&v)) {
        if(u == -1 && v == -1) {
            break;
        }

        if(u == 0 && v == 0) {
            puts("Yes");
            continue;
        }

        memset(vis,0,sizeof(vis));
        ret = true;
        int cnt = 0;
        uf.Init();
        uf.Union(u,v);
        vis[u] = true; vis[v] = true;

        while(scanf("%d %d",&u,&v)) {
            if(u == 0 && v == 0) {
                break;
            }
            vis[u] = true; vis[v] = true;
            if(false == uf.Union(u,v)) {
                ret = false;
            }
        }

        for(int i = 1 ; i <= maxn ; i++) {
            if(vis[i]) {
                cnt ++;
            }
        }

        if(true == ret && uf.GetCount() + cnt - 1 == maxn) {
            puts("Yes");
        }
        else {
            puts("No");
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值