zoukankan      html  css  js  c++  java
  • P3043 [USACO12JAN]牛联盟(并查集+数学)

    (m<n<=1e5,有重边)

     题目表述有问题.....

    给定一张图(不一定联通),每条边可以选择连接的两个点之一,剩余的点可以自己成对,问方案数。

    一开始是真的被吓到了....觉得可写性极低的一题.....

    但是两个结论如果推出来的话就蛮好的了

    solution:

    一开始想:对于每个块进行大小统计,然后组合数乘在一起。但是,有点麻烦:

    有环的情况:对于一个联通块有环,那么就会有n个点,n条边,那就意味着会有一个联通块只有一个单独的点。单独考虑环块(下统称环块)

    看看这个三元环(误),先确定第一条边选左或右两个点,如果第一个边确定了自己的选择,那么它就会占用下一条边的一个选择的权利,也就是:

    如果确定了一条边,就可以确定整个环上的方案数:2

    如果不是裸环的环块呢?

    看这个:

    同上,确定了环上的两个,链的一端就会被占用,也就是说:

    只要是环块,对答案的贡献就是2!

    (伟大的发现)

    考虑无环的情况:

    一共n个点,n-1条边(无向图,不能有环就是树),一共有n种方案。感性证明一下(不知道该怎么理性):

    最后一个点不被选,而这个不被选的点一共有n种情况,这就是n种方案。

    最后根据乘法原理,把所有的方案数乘起来就是ans。

    综上结论,题目就变成了:给定一张图,判断联通块大小,找联通块里的环,统计答案

    联通块?我有并查集!

    找环?我有tarjan!

    (旁边两位z姓大佬给我闷头两巴掌,这题还tarjan?你想变成zwjdd长度???)

    这里介绍一种无向图判环方法(注意,不是找环,只能判断存在

    还是使用并查集,原理就是在一个联通块内,如果遍历边的次数=点的个数,那么这里就存在环。

    貌似是这样哈....我太弱了

    代码(注释版):

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+5;
    const int mod=1e9+7;
    long long f[maxn],num[maxn],n,m,ans=1,c[maxn];
    long long find(long long x){return f[x]==x?x:f[x]=find(f[x]);}//被大佬逼的一行冰茶姬
    //variable declare:num[]:联通块大小,f[]不解释,c[]联通块内边的数量
    int main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) f[i]=i,num[i]=1;//初始化 for(int i=1;i<=m;i++) { long long x,y; scanf("%lld%lld",&x,&y); long long fa=find(x); long long fb=find(y); if(fa!=fb)//合并 { f[fa]=fb; num[fb]+=num[fa];//把联通块大小合并 num[fa]=0;//清零联通块大小 c[fb]+=c[fa]+1;//联通块内多了一条边 } else { c[fb]++;//否则多了一条非树边 } } for(int i=1;i<=n;i++) { if(f[i]==i&&c[i]<num[i])//如果边数没有点数多 ans=ans*num[i]%mod;//统计答案 else if(f[i]==i&&c[i]>=num[i])//否则就是有环,直接*2 ans=(ans<<1)%mod;//记得续命 } printf("%lld",ans);//longlong又出锅了 return 0; }

    (完)

  • 相关阅读:
    MAC使用小技巧(二)
    Swift # GET&POST请求 网络缓存的简单处理
    iOS:Block写递归
    Swift # 项目框架
    uva 11665 Chinese Ink (几何+并查集)
    uva 11859 Division Game
    uva 11916 Emoogle Grid (BSGS)
    uva 11754 Code Feat (中国剩余定理)
    hdu 4347 The Closest M Points(KD树)
    2013多校训练赛第四场 总结
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11546487.html
Copyright © 2011-2022 走看看