BZOJ 4596: [Shoi2016]黑暗前的幻想鄉
阿新 • • 發佈:2019-02-07
迷之正確性的做法
首先觀察資料範圍,哎和ZJOI的小星星一毛一樣啊,會不會給人一種欽定複雜度的感覺啊
於是就亂搞一發,容斥+Matrix Tree定理
莫名其妙地就過了QAQ
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<algorithm> #include<map> #include<set> #include<stack> #include<cstdlib> #include<ctime> #define rep(i,l,r) for(int i=l;i<=r;i++) #define per(i,r,l) for(int i=r;i>=l;i--) #define mmt(a,v) memset(a,v,sizeof(a)) #define tra(i,u) for(int i=head[u];i;i=e[i].next) using namespace std; typedef long long ll; typedef pair<int,int> pr; #define mk(x,y) make_pair(x,y) const int N=20; const int p=(1e9)+7; ll g[N][N]; int n; void print(){ rep(i,1,n){ rep(j,1,n)printf("%lld ",g[i][j]); puts(""); } } ll iabs(ll x){return x<0?-x:x;} ll Gauss(){ ll ans=1; rep(i,1,n-1){ rep(j,i+1,n-1) while(g[j][i]){ ll t=g[i][i]/g[j][i]; rep(k,i,n-1) g[i][k]=(g[i][k]-g[j][k]*t)%p; rep(k,i,n-1) swap(g[i][k],g[j][k]); ans=-ans; } ans=ans*g[i][i]%p; if(!ans)return 0; } return (ans+p)%p; } vector<pr >pl[N]; int main(){ scanf("%d",&n); rep(i,1,n-1){ int m;scanf("%d",&m); while(m--){int u,v;scanf("%d%d",&u,&v);pl[i].push_back(mk(u,v));} } ll ans=0; per(i,(1<<(n-1))-1,0){ int cnt=0; mmt(g,0); rep(j,1,n-1) if(i>>(j-1)&1){ per(k,(int)pl[j].size()-1,0){ int u=pl[j][k].first,v=pl[j][k].second; g[u][u]++;g[v][v]++; g[u][v]--;g[v][u]--; } cnt++; } if((n-cnt)&1)ans=(ans+Gauss())%p; else ans=(ans-Gauss())%p; } printf("%lld\n",(ans+p)%p); return 0; }