bzoj 4596: [Shoi2016]黑暗前的幻想乡
这个题貌似奶了一口trump,,,
本来看到一个公司一条边,而且N是那么科学,肯定要容斥了,然后蛋疼的想应该怎么求生成树。。
本来一开始乱说了个矩阵树定理,然而忘了,就像奇奇怪怪的东西了。。然并卵,正解就是矩阵树定理,IQ--
需要注意的是,求解行列式和一般的线性方程是不一样的,行列式是消去本行,然后交换,变号。。。
1 #include <bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 inline int ra() 5 { 6 int x=0,f=1; char ch=getchar(); 7 while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 8 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 9 return x*f; 10 } 11 12 const int mod=1e9+7; 13 14 LL g[20][20]; 15 int n; 16 vector<pair<int , int > > orz[20]; 17 18 int Gauss() 19 { 20 LL ans=1; 21 for (int i=1; i<n; i++) 22 { 23 for (int j=i+1; j<n; j++) 24 while (g[j][i]) 25 { 26 LL t=g[i][i]/g[j][i]; 27 for (int k=i; k<n; k++) 28 g[i][k]=(g[i][k]-g[j][k]*t)%mod; 29 swap(g[i],g[j]); 30 ans=-ans; 31 } 32 ans=ans*g[i][i]%mod; 33 if (!ans) return 0; 34 } 35 return (ans+mod)%mod; 36 } 37 38 int main(int argc, char const *argv[]) 39 { 40 n=ra(); 41 for (int i=1; i<n; i++) 42 { 43 int m=ra(); 44 for (int j=1; j<=m; j++) 45 { 46 int x=ra(),y=ra(); 47 orz[i].push_back(make_pair(x,y)); 48 } 49 } 50 int ans=0; 51 for (int i=0; i<1<<(n-1); i++) 52 { 53 int cnt=0; memset(g,0,sizeof(g)); 54 for (int j=1; j<n; j++) 55 if ((i>>(j-1))&1) 56 { 57 for (int k=0; k<orz[j].size(); k++) 58 { 59 int x=orz[j][k].first,y=orz[j][k].second; 60 g[x][x]++; g[y][y]++; 61 g[x][y]--; g[y][x]--; 62 } 63 cnt++; 64 } 65 if ((n-cnt)&1) ans=(ans+Gauss())%mod; else ans=(ans-Gauss()+mod)%mod; 66 } 67 printf("%d\n",ans); 68 return 0; 69 }