zoukankan      html  css  js  c++  java
  • 【BZOJ】4596: [Shoi2016]黑暗前的幻想乡

    【题意】给定n个点的无向完全图,有n-1个公司各自分管一部分路,要求所有公司都有修路的生成树数。n<=17。

    【算法】容斥原理+生成树计数(矩阵树定理)

    【题解】每个生成树方案是一个公司有无修路的01排列,定义集合x为公司x有修路的方案集合,则题目要求集合交。

    对于若干集合的集合并补集,即x个公司不修路的方案数,就是除去这x个公司的边的生成树数。

    ans=Σ(-1)^k g(k),0<=k<=n-1。g(k)表示枚举k个公司不修的生成树数。

    复杂度O(2^(n-1)*n^3)。

    注意:

    1.答案变成非负数。

    2.公司边集最大N*N。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=20,MOD=1e9+7;
    int a[maxn][maxn],b[maxn][maxn*maxn][2],sz[maxn],n,ans;//
    bool c[maxn];
    void gcd(int a,int b,int &x,int &y){
        if(!b){x=1;y=0;}
        else{gcd(b,a%b,y,x);y-=x*(a/b);}
    }
    int inv(int a){int x,y;gcd(a,MOD,x,y);return (x%MOD+MOD)%MOD;}
    int det(int n){
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)a[i][j]=(a[i][j]+MOD)%MOD;
        bool y=0;
        for(int i=1;i<=n;i++){
            int r=i;
            for(int j=i+1;j<=n;j++)if(a[j][i]>a[r][i])r=j;
            if(r!=i){y^=1;for(int j=i;j<=n;j++)swap(a[r][j],a[i][j]);}
            int v=inv(a[i][i]);
            for(int j=i+1;j<=n;j++){
                for(int k=n;k>=i;k--){
                    a[j][k]=(a[j][k]-1ll*a[j][i]*v%MOD*a[i][k]%MOD+MOD)%MOD;
                }
            }
        }
        int as=y?MOD-1:1;
        for(int i=1;i<=n;i++)as=1ll*as*a[i][i]%MOD;
        return as;
    }    
    void insert(int u,int v){a[u][v]--;a[v][u]--;a[u][u]++;a[v][v]++;}
    int solve(){
        memset(a,0,sizeof(a));
        for(int i=1;i<n;i++)if(!c[i]){// 
            for(int j=1;j<=sz[i];j++)insert(b[i][j][0],b[i][j][1]);
        }
        return det(n-1);
    }    
    void dfs(int x,int y){
        if(x==n){
            ans=(ans+y*solve())%MOD;
        }
        else{
            c[x]=0;
            dfs(x+1,y);
            c[x]=1;
            dfs(x+1,-y);
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d",&sz[i]);
            for(int j=1;j<=sz[i];j++)scanf("%d%d",&b[i][j][0],&b[i][j][1]);
        }
        ans=0;
        dfs(1,1);
        printf("%d",(ans+MOD)%MOD);//
        return 0;
    }
    View Code
  • 相关阅读:
    Apachebench压力测试
    nodejs调试方法
    chrome 内存泄漏如何定位
    nodejs模块路径alias
    云计算基本概念IaaS,PaaS,SaaS和Serverless
    单点登录sso
    彻底删除mysql服务
    Java-Tomcat for Mac配置
    访问日志不记录静态文件 访问日志切割 静态元素过期时间
    Mac eclipse 连接安卓手机调试 adb
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8149197.html
Copyright © 2011-2022 走看看