bzoj4596: [Shoi2016]黑暗前的幻想乡
一波卡线AC美滋滋。。
这题以前看过,但是不会矩阵树定理就弃了
今天再看还是不是很会。。
状压一波,0/1表示这个公司取还是不取,那么就把这个公司能够修的边放进图弄基尔霍夫矩阵求行列式,但是这样并不能保证这个公司必定被取
考虑容斥,就要减去这个公司一定不取的情况……
假如奇偶性和n-1就加,否则就减
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9+7; LL MOD(LL x){return (x%mod+mod)%mod;} int n; LL kf[20][20]; LL gethls() { LL ans=1,tp=1; for(int i=2;i<=n;i++) { for(int j=i+1;j<=n;j++) { int x=i,y=j; while(kf[y][i]!=0) { LL t=kf[x][i]/kf[y][i]; for(int k=i;k<=n;k++) kf[x][k]=MOD(kf[x][k]-MOD(kf[y][k]*t)); swap(x,y); } if(x!=i) { tp=0-tp; for(int k=2;k<=n;k++) swap(kf[x][k],kf[y][k]); } } ans=MOD(ans*kf[i][i]); } ans=MOD(ans*tp); return ans; } struct repair { int x,y; }c[20][410];int clen[20]; int main() { scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d",&clen[i]); for(int j=1;j<=clen[i];j++) scanf("%d%d",&c[i][j].x,&c[i][j].y); } int lim=(1<<(n-1))-1;LL ans=0; for(int zt=0;zt<=lim;zt++) { int o=0; memset(kf,0,sizeof(kf)); for(int i=1;i<=n;i++) { if( (zt& (1<<(i-1)) )>0) { o++; for(int j=1;j<=clen[i];j++) { kf[c[i][j].x][c[i][j].x]++; kf[c[i][j].y][c[i][j].y]++; kf[c[i][j].x][c[i][j].y]--; kf[c[i][j].y][c[i][j].x]--; } } } if((n-1)%2==o%2)ans=MOD(ans+gethls()); else ans=MOD(ans-gethls()); } printf("%lld\n",ans); return 0; }
pain and happy in the cruel world.