4596: [Shoi2016]黑暗前的幻想乡
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 559 Solved: 325
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
2 3 2 4 2
5 2 1 3 1 3 2 4 1 4 3
4 2 1 3 2 4 1 4 2
Sample Output
HINT
Source
容斥一下让哪几个公司来修就可以了,然后每次矩阵树定理求一下方案树就可以了。
这里是直接高斯消元的,没有辗转相除的形式,但是好像矩阵树是保证还是桌面回事,不需要的。
1 #pragma GCC optimize(2) 2 #pragma G++ optimize(2) 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdio> 7 #include<cstring> 8 9 #define ll long long 10 #define N 22 11 #define mod 1000000007 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 17 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 21 int n; 22 int a[N][N],f[N][N],ans; 23 int cnt,hed[N]; 24 struct Node 25 { 26 int x,y,nxt; 27 }e[10007]; 28 29 void add(int u,int x,int y) 30 { 31 e[++cnt].x=x; 32 e[cnt].y=y; 33 e[cnt].nxt=hed[u]; 34 hed[u]=cnt; 35 } 36 int cal(int num)//矩阵树定理是每个点的度,若x-y有边则x,y -1,y,x -1然后消去一行,下三角消元 37 { 38 //这里好处是num为n-1了,已经减去一行了。 39 for (int i=1;i<=num;i++) 40 for (int j=1;j<=num;j++) 41 a[i][j]=f[i][j]; 42 int ans=1; 43 for (int i=1;i<=num;i++) 44 { 45 for (int j=i+1;j<=n;j++) 46 while(a[j][i]) 47 { 48 int t=a[i][i]/a[j][i]; 49 for (int k=i;k<=n;k++)a[i][k]=(a[i][k]-(ll)a[j][k]*t%mod)%mod; 50 for (int k=i;k<=n;k++)swap(a[i][k],a[j][k]); 51 ans=-ans;//ans去反是因为斜对角线上负数的个数 52 } 53 if(!a[i][i])return 0; 54 ans=(ll)ans*a[i][i]%mod; 55 } 56 return ans; 57 } 58 void dfs(int x,int y) 59 { 60 if (x==n)//就n-1个人 61 { 62 (ans+=y*cal(n-1))%=mod; 63 return; 64 } 65 dfs(x+1,y); 66 67 for (int i=hed[x];i!=-1;i=e[i].nxt) 68 { 69 int u=e[i].x,v=e[i].y; 70 f[u][u]--,f[v][v]--,f[u][v]++,f[v][u]++; 71 } 72 dfs(x+1,-y); 73 for (int i=hed[x];i!=-1;i=e[i].nxt) 74 { 75 int u=e[i].x,v=e[i].y; 76 f[u][u]++,f[v][v]++,f[u][v]--,f[v][u]--; 77 } 78 } 79 int main() 80 { 81 memset(hed,-1,sizeof(hed)); 82 n=read(); 83 for (int i=1;i<n;i++) 84 { 85 int number=read(); 86 for (int j=1;j<=number;j++) 87 { 88 int x=read(),y=read(); 89 add(i,x,y); 90 f[x][x]++,f[y][y]++,f[x][y]--,f[y][x]--; 91 } 92 } 93 dfs(1,1); 94 printf("%d\n",(ans%mod+mod)%mod); 95 }