hdu 3926 并查集

来源:互联网 发布:p2p网络借贷管理办法 编辑:程序博客网 时间:2024/05/21 10:42

链接

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

题意


有n个小孩,他们之间手拉手,形成一个图,图的每个点都是0、1、2个度。在给出一个图,判断是否两个图同构。


解析


因为图的每个节点的度都是0、1、2。因此可以拿并查集做,但是你要记录每个块的是否有环,注意在一个块为两个节点的时候,出现不了环。最后判断环的个数和每个块的节点个数是否相同即可。


代码

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <map>using namespace std;const int maxn = 100000+10;int num;typedef long long LL;int fa[maxn], pa[maxn], num1[maxn], num2[maxn];vector<int>g[maxn];int deg[maxn];void init() {    for (int i=0; i<maxn; i++)        fa[i] = i, pa[i] = i, num1[i] = 1, num2[i] = 1;}int Find(int x, int *f) {    return x==f[x]?x:f[x] = Find(f[x], f);}void Union(int u, int v, int *f, int *num) {    u = Find(u, f);    v = Find(v, f);    if (u != v) {        num[v] += num[u];        num[u] = 0;        f[u] = v;    }}int main(){    int T;    scanf("%d", &T);    int ca=1;    while (T--) {        int n, m;        init();        int flag = 0, flag1 = 0;        scanf("%d%d", &n, &m);        for (int i=0; i<m; i++) {            int u, v;            scanf("%d%d", &u, &v);            int x = Find(u, fa);            int y = Find(v, fa);            if (x == y && num1[x] != 2)                flag++;            Union(u, v, fa, num1);        }        int _n, _m;        scanf("%d%d", &_n, &_m);        for (int i=0; i<_m; i++) {            int u , v;            scanf("%d%d", &u, &v);            int x = Find(u, pa);            int y = Find(v, pa);            if (x == y && num2[x] != 2)                flag1++;            Union(u, v, pa, num2);        }        if (n != _n)        {            printf("Case #%d: NO\n",ca++);            continue;        }        map<int, int>f;        map<int, int>p;        for (int i=1; i<=n; i++) {            if (Find(i, fa) == i)            f[num1[i]]++;         }        for (int i=1; i<=_n; i++) {            if (Find(i, pa) == i)            p[num2[i]]++;        }        int P = 0;        int num=0;        for (map<int, int>::iterator it=f.begin(); it!=f.end(); it++) {            if ((*it).second == p[(*it).first])                num++;            else                P = 1;        }        if (num != p.size())            P = 1;        if (P == 0 && flag1 == flag)            printf("Case #%d: YES\n", ca++);        else            printf("Case #%d: NO\n", ca++);    }    return 0;}
0 0