zoukankan      html  css  js  c++  java
  • P4208 [JSOI2008]最小生成树计数

    P4208 [JSOI2008]最小生成树计数


    讲课的时候提到了这个妙极了的思想,于是就把这题做了。

    有个结论:相同边权的边集不论怎么选,对最小生成树的贡献都相同(选的数量都会相同,而且连完之后图的连通性也会相同)

    所以可以把不同边权的边分开来看,答案就是每种边权的方案之积。

    于是就可以愉快地暴力了:

    1. 从小到大枚举边权;
    2. 拿出这个边权的所有边,并算出要连多少条边,以及连接这些边会连通哪些点;
    3. 暴力枚举选哪些边,加入方案里;
    4. 最后把现在通的集合缩起来。

    复杂度上界是(O(m 2^{10} n)),然而远远达不到,因为(2^{10})最大也就是(C ^{5}_{10}),而且因为要缩点,n也不会一直是n。

    emmm还有,注意判断无解情况

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    typedef int mmp;
    #define vd void
    #define rg register
    #define il inline
    #define sta static
    il int gi(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    namespace YYB{
        int n,m;
        struct edge{int u,v,w;}yyb[1001];
        int operator <(const edge&a,const edge&b){return a.w<b.w;}
        int fa[101];
        il int find(int*fa,int x){return fa[x]==x?x:fa[x]=find(fa,fa[x]);}
        il bool Union(int*fa,int x,int y){
            x=find(fa,x),y=find(fa,y);
            if(x>y)swap(x,y);
            if(x!=y){fa[y]=x;return 1;}
            return 0;
        }
        il vd solve(){
            n=gi(),m=gi();
            for(rg int i=1;i<=m;++i)yyb[i].u=gi(),yyb[i].v=gi(),yyb[i].w=gi();
            sort(yyb+1,yyb+m+1);
            for(rg int i=1;i<=n;++i)fa[i]=i;
            int ans=1;
            for(rg int i=1;i<=m;++i){
                int j=i;while(yyb[j+1].w==yyb[i].w)++j;
                for(rg int s=i;s<=j;++s)yyb[s].u=find(fa,yyb[s].u),yyb[s].v=find(fa,yyb[s].v);
                int fafa[101],tot=0;
                for(rg int s=1;s<=n;++s)fafa[s]=s;
                for(rg int s=i;s<=j;++s)if(Union(fafa,yyb[s].u,yyb[s].v))++tot;
                int res=0;
                for(rg int s=0;s<1<<(j-i+1);++s){
                    int cnt=0;for(rg int p=s;p;p-=p&-p)++cnt;
                    if(cnt!=tot)continue;
                    for(rg int q=1;q<=n;++q)fafa[q]=q;
                    int tot_=0;
                    for(rg int q=i;q<=j;++q)
                        if(s&(1<<q-i))
                            if(Union(fafa,yyb[q].u,yyb[q].v))++tot_;
                    if(tot_==tot)++res;
                }
                for(rg int s=i;s<=j;++s)Union(fa,yyb[s].u,yyb[s].v);
                ans=ans*res%31011;
                i=j;
            }
            for(rg int i=1;i<=n;++i)if(find(fa,i)!=1)ans=0;
            printf("%d
    ",ans);
        }
    }
    mmp main(){
        //freopen("bzoj_1016.in","r",stdin);
        //freopen("bzoj_1016.out","w",stdout);
        YYB::solve();
        return 0;
    }
    
  • 相关阅读:
    我的第九个java程序--spring和mybatis整合(java project)
    php 批量插入字段
    php 遍历静态html成文章列表
    把world转成html
    java 读取world的图片 并把图片路径存入数据库
    我的第八个java程序--读取word内容
    我的第7个java程序--把java web项目改为java project项目--mybatis
    我的第六个java程序 spring-bean
    学习spring2--跟我一起学Spring 3(3)–使用Spring开发第一个HelloWorld应用
    学习spring1--跟我一起学Spring 3(2)–开发环境配置
  • 原文地址:https://www.cnblogs.com/xzz_233/p/8656490.html
Copyright © 2011-2022 走看看