zoukankan      html  css  js  c++  java
  • 【bzoj4596】黑暗前的幻想乡

    把每个公司能连的边都看做独立的边,即在所有能连的边里随便连,矩阵树。

    显然有不合法的情况,每个公司只能连一条边,考虑容斥:

    ans=sigma随便连-sigma一个公司不连+sigma两个公司不连-sigma三个公司不连……

    容斥写错了safufu地调了半天消元QAQ

    #include<bits/stdc++.h>
    #define maxn 20
    #define MOD 1000000007
    #define ll long long
      
    using namespace std;
      
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
      
    int a[maxn][maxn],D[maxn][maxn],A[maxn][maxn];
      
    int gauss(int n){
        int ret=1;
        for(int i=1;i<=n;++i){
            for(int j=i+1;j<=n;++j){
                int A=a[i][i],B=a[j][i];
                while(B){
                    int t=A/B;A%=B;swap(A,B);
                    for(int k=i;k<=n;++k)a[i][k]=(a[i][k]-1ll*t*a[j][k]%MOD)%MOD;
                    for(int k=i;k<=n;++k)swap(a[i][k],a[j][k]);
                    ret=-ret;
                }
            }
            if(!a[i][i])return 0;
            ret=1ll*ret*a[i][i]%MOD;
        }
        return (ret+MOD)%MOD;
    }
      
    int n,s[maxn],num[maxn],u[maxn][maxn*maxn],v[maxn][maxn*maxn];
      
    void build(){
        memset(D,0,sizeof(D));
        memset(A,0,sizeof(A));
        for(int i=1;i<n;++i)if(s[i]){
            for(int j=1;j<=num[i];++j){
                int f1=u[i][j],f2=v[i][j];
                ++D[f1][f1];++D[f2][f2];
                ++A[f1][f2];++A[f2][f1];
            }
        }
        for(int i=1;i<n;++i)
            for(int j=1;j<n;++j)
                a[i][j]=D[i][j]-A[i][j];
    }
      
    int ans;
      
    void dfs(int p,int f){
        if(p>=n){
            f=n-1-f;
            if(f&1)f=-1;else f=1;
            build();int gs=gauss(n-1);
            ans=(ans+f*gs)%MOD;
            return;
        }
        s[p]=1;
        dfs(p+1,f+1);
        s[p]=0;
        dfs(p+1,f);
    }
      
    int main(){
        n=read();
        for(int i=1;i<n;++i){
            num[i]=read();
            for(int j=1;j<=num[i];++j){
                u[i][j]=read();v[i][j]=read();
            }
        }
        dfs(1,0);
        printf("%d
    ",(ans%MOD+MOD)%MOD);
        return 0;
    }
  • 相关阅读:
    shell基础
    函数属性
    this的使用
    循环
    正则表达式中的方法
    判断是不是数组
    ECMAScript5中数组方法
    ECMAScript3中数组方法
    break和continue、return的区别
    用来枚举属性的对象工具函数
  • 原文地址:https://www.cnblogs.com/illya/p/7603521.html
Copyright © 2011-2022 走看看