最小產生樹的變形題,最大產生樹。
這道題顯然用Kruskal演算法可以直接計算最小產生樹的值,但是題目需要判斷最小產生樹是否存在,因此我們引入變數node_num表示樹中的節點數。
比較樹中的節點樹與總節點樹即可。
ps.為什麼是單向邊。
#include <cstdio>#include <algorithm>using namespace std;const int maxn = 1000 + 10;const int maxm = 2*20000 + 10;int par[maxn];int rk[maxn];struct edge { int from; int to; int cost;};edge es[maxm];int node_num;void init(int n) { for (int i = 0; i < n; i++) { par[i] = i; rk[i] = 0; }}int find(int x) { if (par[x] == x) { return x; } else { return par[x] = find(par[x]); }}void unite(int x, int y) { x = find(x); y = find(y); if (x == y) { return; } if (rk[x] < rk[y]) { par[x] = y; } else { par[y] = x; if (rk[x] == rk[y]) { rk[x]++; } }}bool same(int x, int y) { return find(x) == find(y);}bool comp(const edge& e1, const edge& e2) { return e1.cost > e2.cost;}int kruskal(int n, int m) { sort(es, es + m, comp); init(n); int res = 0; node_num = 1; for (int i = 0; i < m; i++) { edge e = es[i]; if (!same(e.from, e.to)) { unite(e.from, e.to); res += e.cost; node_num++; } } return res;}int main(int argc, char const *argv[]) { int n, m; scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) { scanf("%d%d%d", &es[i].from, &es[i].to, &es[i].cost); es[i].from--; es[i].to--; } int ans = kruskal(n, m); if (node_num < n) { puts("-1"); } else { printf("%d\n", ans); } return 0;}