->类似题目:https://blog.csdn.net/weixin_40588429/article/details/87211032
来源:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2124
经典有向图最小生成树
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
const int maxn = 1e3 + 3;
const int inf = 0x3f3f3f3f;
int n, m, vis[maxn], in[maxn];
int val[maxn][maxn], pre[maxn];
void check_link(int u) {
vis[u] = 1;
for(int v = 0; v < n; v++) if(!vis[v]) {
if(val[u][v] < inf)
check_link(v);
}
}
int undirected_mst(int u) {
memset(vis, 0, sizeof(vis[0]) * n);
memset(in, 0, sizeof(in[0]) * n);
check_link(u);
for(int i = 0; i < n; i++)
if(!vis[i]) return -1;
int res = 0;
while(true) {
for(int i = 0; i < n; i++) if(i != u && !in[i]) {
val[i][i] = inf, pre[i] = i;
for(int j = 0; j < n; j++) if(!in[j] && val[j][i] < val[pre[i]][i]) {
pre[i] = j;
}
}
int i;
for(i = 0; i < n; i++) if(!in[u] && i != u) {
int cnt = 0, j = i;
while(j != u && cnt <= n && pre[j] != i) cnt++, j = pre[j];
if(cnt > n || j == u) continue;
break;
}
if(i >= n) {
for(int j = 0; j < n; j++) if(!in[j] && j != u) res += val[pre[j]][j];
break;
}
memset(vis, 0, sizeof(vis[0]) * n);
int j = i;
do {
res += val[pre[j]][j];
j = pre[j];
vis[j] = in[j] = 1;
} while(j != i);
in[i] = 0;
for(int k = 0; k < n; k++) if(vis[k]) {
for(int j = 0; j < n; j++) if(!vis[j]) {
if(val[k][j] < val[i][j]) val[i][j] = val[k][j];
if(val[j][k] < inf && val[j][k] - val[pre[k]][k] < val[j][i])
val[j][i] = val[j][k] - val[pre[k]][k];
}
}
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
for(int cas = 1; cas <= T; cas++) {
cout << "Case #" << cas << ": ";
cin >> n >> m;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
val[i][j] = inf;
for(int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
val[u][v] = min(val[u][v], w);
}
int ans = undirected_mst(0);
if(ans != -1) cout << ans << endl;
else cout << "Possums!" << endl;
}
}