[SHOI2016]黑暗前的幻想乡

题意

n1n−1个公司,每个公司能修一些边,求每条边都让不同的公司来修的生成树的方案数


题解

看到这种”每个都要”的题目就往容斥方面想一想

那么ans=ans=所有都选了的生成树个数1−1个没选的+2+2个没选的−…

生成树个数就可以用直接用矩阵树定理求就好了

然后这题模数是一个质数,所以可以直接求逆元

#include
#define fp(i,a,b) for(register int i=a,I=b+1;i
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=20,P=1e9+7;
typedef int arr[N];
typedef long long ll;
struct eg{int nx,u,v;}e[8005];
int n,ce,ans;arr fi,a[N],G[N];
inline int pls(int a,int b){return a+=b,a>=P?a-P:a;}
inline int sub(int a,int b){return a-=b,a<0?a+P:a;}
inline int fpm(int a,int b){int x=1;for(;b;b>>=1,a=(ll)a*a%P)if(b&1)x=(ll)x*a%P;return x;}
inline int det(int n){
    int ans=1,f=1,t,inv,mx;
    fp(i,1,n)fp(j,1,n)G[i][j]=pls(a[i][j],P);
    fp(i,1,n){mx=i;
        fp(j,i,n)if(G[j][i]>G[mx][i])mx=j;
        if(mx^i){fp(k,i,n)swap(G[i][k],G[mx][k]);f=-f;}
        inv=fpm(G[i][i],P-2);
        fp(j,i+1,n)if(G[j][i]){
            t=(ll)G[j][i]*inv%P;
            fp(k,i,n)G[j][k]=sub(G[j][k],(ll)G[i][k]*t%P);
        }ans=(ll)ans*G[i][i]%P;
    }
    return pls(P,f*ans);
}
void dfs(int x,int y){
    if(x==n)return y&1?ans=sub(ans,det(n-1)):ans=pls(ans,det(n-1)),void();
    dfs(x+1,y);
    for(int i=fi[x];i;i=e[i].nx){
        int u=e[i].u,v=e[i].v;
        --a[u][u],--a[v][v],++a[u][v],++a[v][u];
    }
    dfs(x+1,y+1);
    for(int i=fi[x];i;i=e[i].nx){
        int u=e[i].u,v=e[i].v;
        ++a[u][u],++a[v][v],--a[u][v],--a[v][u];
    }
}
inline void add(int i,int u,int v){e[++ce]={fi[i],u,v},fi[i]=ce;}
int main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    scanf("%d",&n);
    fp(i,1,n-1){
        int m,u,v;scanf("%d",&m);
        fp(j,1,m)scanf("%d%d",&u,&v),add(i,u,v),++a[u][u],++a[v][v],--a[u][v],--a[v][u];
    }
    dfs(1,0);
    printf("%d",ans);
return 0;
}

你可能感兴趣的:(#,矩阵树,容斥)