2019 蓝桥杯国赛 B 组模拟赛 E 蒜头图 (并查集判环)


 

思路:

我们看条件,发现满足条件的子图无非就是一些环构成的图,

因为只有形成环,才满足边的两个点都在子图中,并且子图中节点的度是大于0的偶数。

那么如果当前有k个环,我们可以选2^k-1个子图,为什么?

我们从这k个环中选择 1~n个都可以满足条件,那么就是C(k,1)+C(k,2)+C(k,3)+...+C(k,n) = 2^k-1

接下来就看如何判定当前图有多少个环?

我们每加一个边,如果加入之前,这个边的两个端点a,b,如果a和b已经在图中联通了,那么加上这条边必多一个子图为环。

我们用并查集来维护两个节点是否联通即可。

 

细节见代码:

#include<bits/stdc++.h>
using namespace std;

const int mod = 1046513837;
int n,m,f[200500];

int find(int x){
    return f[x] == x ? x : f[x] = find(f[x]);
}

void merge(int a,int b){
    int x = find(a);
    int y = find(b);
    if(x != y ) f[x] = y;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) f[i] = i;
    long long ans = 1;
    for(int i=1 ;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        int x = find(a), y = find(b);
        if(x == y){//这里如果 两个点祖先一样 说明找到环了
            ans <<= 1;
            if(ans > mod) ans -= mod;
        }else merge(a,b);
        printf("%lld\n",ans-1);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/qieqiemin/p/10915103.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值