参考的有这位大佬的博客:https://blog.csdn.net/clover_hxy/article/details/69397184
最小生成树的两个性质:
(1)不同的最小生成树中,每种权值的边出现的个数是确定的
(2)不同的生成树中,某一种权值的边连接完成后,形成的联通块状态是一样的
那么我们其实可以把每种权值的处理看成是分开的好几步,然后根据乘法原理,将每一步得到的结果相乘。
通过举例子进行说明,下图中s1,s2,s3表示已经处理好的3个连通块,虚线表示一组同权值的边。加入这组边后s1,s2,s3可以连通。
将已经计算好的连通块缩成一个点,那么就变成了一个独立的图的生成树问题,可以用矩阵树定理求解。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<cmath>
#include<map>
using namespace std;
#define N 1005
int n, m;
int p[N];
int ex[105];
int ts[N], tt[N];
int tans = 0;
int exist[N];
int C[12][12];
struct edge {
int v1, v2;
int w;
}E[N];
bool cmp(edge x, edge y) {
return x.w < y.w;
}
void init() {
for (int i = 1; i <= n; i++) {
p[i] = i;
exist[i] = 0;
}
}
int find(int x) {
if (x != p[x]) {
p[x] = find(p[x]);
}
return p[x];
}
void buM(int l, int r) {
init();
for (int i = 0; i < m; i++) {
if ((i<l || i>r)&&ts[i]) {
int x = find(E[i].v1);
int y = find(E[i].v2);
if (x != y) {
if (x > y)
swap(x, y);
p[y] = x;
}
}
}
}
int matrixtheorem(int t) {
int ht = 1;
if (t == 3)
return abs(C[2][2] * C[3][3] - (C[2][3] * C[3][2]));
t = t - 1;
int mu1 = 1;int mu2 = 1;int sum1 = 0;int M = 0;
for (int i = 0; i <= t-ht; i++) {
mu1 = 1;
mu2 = 1;
for (int j = 1; j <= t; j++) {
int h = (j + i) > t ? (j + i - t) : j + i;
mu1 *= C[j + 1][h + 1];
mu2 *= C[j + 1][t + 2 - h];
}
sum1 += (mu1 - mu2);
}
return abs(sum1);
}
int main() {
memset(ts, 0, sizeof(ts));
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &E[i].v1, &E[i].v2, &E[i].w);
}
sort(E, E + m, cmp);
init();
for (int i = 0; i < m; i++) {
int x = find(E[i].v1);
int y = find(E[i].v2);
if (x != y) {
ts[i] = 1;
if (x > y)swap(x, y);
p[y] = x;
}
}
int rex = E[0].w;
int ansx = 0, tans = 0;
for (int i = 0; i < m; i++) {
if (E[i].w == rex) {
ansx++;
}
else {
rex = E[i].w;
tt[tans++] = ansx;
i--;
ansx = 0;
}
}
tt[tans++] = ansx;
int l, r;
l = 0; r = 0;
E[m].w = -1;
int ttt = tans;
for (int i = 0; i < ttt; i++) {
r = l + tt[i] - 1;
int sums = 0;
for (int j = l; j <= r; j++) {
sums += ts[j];
}
if (l == r || sums <= 0) {
l = r + 1;
ex[tans++] = 1;
continue;
}
memset(C, 0, sizeof(C));
buM(l, r);
int res[N];int t = 0;int flag = 0;
for (int j = l; j <= r; j++) {
int x = find(E[j].v1), y = find(E[j].v2);
if (x != y) {
flag = 1;
if (!exist[x]) {
exist[x] = 1;
res[x] = ++t;
}
if (!exist[y]) {
exist[y] = 1;
res[y] = ++t;
}
//cout << res[x] << " " << res[y] << endl;
C[res[x]][res[y]]--; C[res[y]][res[x]]--;
C[res[x]][res[x]]++; C[res[y]][res[y]]++;
}
}
if (!flag) {
l = r + 1;
ex[tans++] = 1;
continue;
}
/*for (int j = 1; j <= t; j++) {
for(int k=1;k<=t;k++)
cout << C[j][k] << " ";
cout << endl;
}*/
if (t == 2)
ex[tans++] = C[2][2];
else
ex[tans++] = matrixtheorem(t);
l = r + 1;
}
int mu = 1;
for (int i = 0; i < tans; i++) {
//cout << ex[i] << endl;
if (ex[i] == 0)
continue;
mu *= ex[i];
}
cout << mu << endl;
return 0;
}