HDU - 3926 Hand in Hand(并查集+同构图判断)

Hand in Hand

HDU - 3926

因为一个点只能连两条边,所以要么成环,要么成链。
判断两次形成的图是否同构图。

同构图是什么

把图的边想象成可以自由活动的绳子,在绳子任意变动期间的图形都是同构图。典型例子是五边形和五角星。

如何判断同构图

思路之一:通过并查集确定环数/链数,和环内/链内的人数,再排序进行比较。

我的代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10005;
int t, n1, m1, n2, m2;
int f1[maxn], f2[maxn];
int root1[maxn], root2[maxn]; //记录每个集合有多少个数
int u1[maxn], u2[maxn], v1[maxn], v2[maxn];
int a[maxn], b[maxn];
int loop1, loop2;

void init(){
    for(int i = 1; i <= maxn; i++)
        f1[i] = i, f2[i] = i, root1[i] = root2[i] = 1;
    loop1 = 0, loop2 = 0;
}

int Find(int f[], int x){
    if(f[x] == x) return x;
    else return f[x] = Find(f, f[x]);
}

int main(){
    cin >> t;
    int num = 0;
    while(t--){
        init();
        num++;
        cin >> n1 >> m1;
        for(int i = 1; i <= m1; i++){
            cin >> u1[i] >> v1[i];
            int fa = Find(f1, u1[i]);
            int fb = Find(f1, v1[i]);
            if(fa == fb) {a[++loop1] = root1[fa]; }//成环
            //不成环则更新集合个数。
            else {f1[fa] = fb; root1[fb] += root1[fa]; root1[fa] = 0; }
        }
        cin >> n2 >> m2;
        for(int i = 1; i <= m2; i++){
            cin >> u2[i] >> v2[i];
            int fa = Find(f2, u2[i]);
            int fb = Find(f2, v2[i]);
            if(fa == fb) { b[++loop2] = root2[fa];} //成环
            else {f2[fa] = fb; root2[fb] += root2[fa]; root2[fa] = 0; }
        }
        printf("Case #%d: ", num);
        if(loop1 != loop2){cout << "NO" << endl;}
        else{
            int flag = 0;
            sort(a+1, a+loop1+1);
            sort(b+1, b+loop2+1);
            for(int i = 1; i <= loop1; i++){
                if(a[i] == b[i]) continue;
                else { flag = 1; break; }
            }
            if(flag) cout << "NO" << endl;
            else cout << "YES" << endl;
        }
    }

}

wa点

对于成环的集合,我们要另外保存,并且最后将环内的个数升序排序比较。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值