生成树计数

Matrix-Tree定理(Kirchhoff矩阵-树定理)解决简单平凡无向图的生成树计数问题最有力的武器之一

1、G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时,dij=0;当i=j时,dij等于vi的度数。

2、G的邻接矩阵A[G]也是一个n*n的矩阵, 并且满足:如果vi、vj之间有边直接相连,则aij=1,否则为0。

我们定义G的Kirchhoff矩阵(也称为拉普拉斯算子)C[G]为C[G]=D[G]-A[G],则Matrix-Tree定理可以描述为:G的所有不同的生成树的个数等于其Kirchhoff矩阵C[G]任何一个n-1阶主子式的行列式的绝对值。所谓n-1阶主子式,就是对于r(1≤r≤n),将C[G]的第r行、第r列同时去掉后得到的新矩阵,用Cr[G]表示。

Cayley定理:完全图的生成树个数为n^(n-2).推论:有根完全图的生成树个数为n^(n-1)

long det(long[][] mat, int n) {
		long ans = 1;
		for (int i = 0; i < n; i++) {
			for (int j = i + 1; j < n; j++)
				while (mat[i][j] != 0) {
					long t = mat[i][i] / mat[i][j];
					for (int k = 0; k < n; k++)
						mat[k][i] -= mat[k][j] * t;
					long temp;
					for (int k = 0; k < n; k++) {
						temp = mat[k][i];
						mat[k][i] = mat[k][j];
						mat[k][j] = temp;
					}
					ans = -ans;
				}
			if (mat[i][i] == 0)
				return 0;
		}
		for (int i = 0; i < n; i++)
			ans *=  mat[i][i];
		return ans;
	}
	void run() {
		int n = scan.nextInt();
		int m = scan.nextInt();
		long map[][] = new long[n][n];
		while (m-- > 0) {
			int a = scan.nextInt() - 1;
			int b = scan.nextInt() - 1;
			if (map[a][b] == -1)
				continue;
			map[a][b]--;
			map[b][a]--;
			map[a][a]++;
			map[b][b]++;
		}
		System.out.println(det(map, n - 1));
	}




你可能感兴趣的:(生成树计数)