题目描述:
一个由n个部门组成的公司现在需要分层,但是由于员工间的一些小小矛盾,使得他们并不愿意做上下级,问在满足他们要求以后有多少种分层的方案数?
解题思路:
生成树计数模板题,建立Kirchhoff矩阵,利用Matrix_tree定理求解。
Kirchhoff矩阵:假设G为n*n矩阵,C为G的入度矩阵(i==j时,C[i][j]等于i的入度;i!=j时,C[i][j]等于零),A为G的邻接矩阵,那么就有Kirchhoff矩阵等于C-A。
Matrix_tree定理:G的不同生成树的个数等于其所对应的kirchhoff矩阵的n-1阶行列式的绝对值(PS:n-1阶行列式等于Kirchhoff矩阵减去第r行,第r列后所形成的矩阵,其中1<=r<=n)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 typedef long double LD; 7 const int maxn = 60; 8 const LD sng = 1e-8; 9 10 LD b[maxn][maxn]; 11 int a[maxn][maxn]; 12 bool Exp(LD x) 13 { 14 return ((x>=0)?x:-x)<sng; 15 } 16 LD MTree (int n) 17 { 18 int sign = 0, j; 19 LD res = 1; 20 for (int i=0; i<n; i++) 21 { 22 if (Exp(b[i][i])) 23 { 24 for (j=i+1; j<n; j++) 25 if (!Exp(b[j][i])) 26 break; 27 if (j == n) 28 return 0; 29 for (int k=i; k<n; k++) 30 swap (b[i][k], b[j][k]); 31 sign ++; 32 } 33 res *= b[i][i]; 34 for (j=i+1; j<n; j++) 35 b[i][j] /= b[i][i]; 36 for (j=i+1; j<n; j++) 37 for (int k=i+1; k<n; k++) 38 b[j][k] -= b[j][i] * b[i][k]; 39 } 40 if (sign % 2) 41 res = -res; 42 return res; 43 } 44 int main () 45 { 46 int n, m, k; 47 while (scanf ("%d %d %d", &n, &m, &k) != EOF) 48 { 49 memset (a, 0, sizeof(a)); 50 memset (b, 0, sizeof(b)); 51 while (m --) 52 { 53 int u, v; 54 scanf ("%d %d", &u, &v); 55 u--, v--; 56 a[u][v] = a[v][u] = 1; 57 } 58 for (int i=0; i<n; i++) 59 for (int j=0; j<n; j++) 60 if (!a[i][j] && i != j) 61 { 62 b[i][i] ++; 63 b[i][j] = -1; 64 } 65 printf ("%.0f\n", (double)MTree (n - 1)); 66 } 67 return 0; 68 }