给定无向图邻接矩阵,求该无向图生成树的个数
神奇的Matrix-Tree定理:
设矩阵G[N][N]为图的度数矩阵, G[i][i] = i点度数,其余元素为0
设矩阵A[N][N]为图的邻接矩阵
则定义Kirchhoff矩阵为G[N][N] - A[N][N]
那么该无向图的生成树个数为Kirchhoff矩阵任意n-1阶主子式的行列式值。
求行列式用Gauss消元就行,注意主元的选取。 时间复杂度O(n^3)
以下为代码,题目是CodeCraft 2007 的第四题。
参考文献可参见2007年国家集训队,周冬的论文。
- #include <iostream>
- #include <cmath>
- const int N = 20;
- double kir[N][N];
- int n;
- double det()
- {
- int i, j, k;
- double t;
- double ans = 1.;
- for(i = 1; i < n; i++)
- {
- int tmp;
- double num = 0;
- for(j = i; j < n; j++)
- {
- if(fabs(kir[j][i]) > num)
- {
- num = fabs(kir[j][i]);
- tmp = j;
- }
- }
- if(num < 1e-9) return 0;
- ans *= num;
- if(tmp != i)
- {
- for(k = i; k < n; k++)
- {
- t = kir[i][k]; kir[i][k] = kir[tmp][k]; kir[tmp][k] = t;
- }
- }
- for(j = i + 1; j < n; j++)
- {
- double factor = -1.0 * kir[j][i] / kir[i][i];
- for(k = i; k < n; k++)
- kir[j][k] += factor * kir[i][k];
- }
- }
- return ans;
- }
- int main()
- {
- int i, j, k, ca;
- for(scanf("%d",&ca); ca; ca--)
- {
- memset(kir, 0, sizeof(kir));
- scanf("%d",&n);
- for(i = 1; i <= n; i++)
- for(j = 1; j <= n; j++){
- scanf("%d",&k);
- kir[i][i] += k;
- if(i != j) kir[i][j] = -k;
- }
- printf("%.0lf/n", det());
- }
- return 0;
- }