【hdu3367】Pseudoforest(偽森林)
阿新 • • 發佈:2017-09-21
return style pid cmp acm 防止 include 不能 fine
http://acm.hdu.edu.cn/showproblem.php?pid=3367
題目大意
偽森林就是一個無向圖,這個無向圖有多個連通塊且每個連通塊只有一個簡單環。
給你一個無向圖,讓你找這個圖的一個最大生成偽森林(即邊權之和最大)。
題解
考慮到用Kruscal算法搞最大生成樹時,每次加入一條邊之前都必須保證邊的這兩點在之前屬於兩個連通塊,就是為了防止出現環。
即如果加入的邊的兩點在一個沒有環的連通塊裏的話,就會出現一個環。
那麽我們把Kruscal算法改造一下,如果這條邊的兩點在同一個沒有環的連通塊的話,仍然加入這條邊,並把這個連通塊標記有環。把所有的邊都試著加入一遍後就可以得到最終答案。
還要註意如果這條邊的兩點在不同的連通塊,但是兩個連通塊都有環,那麽這條邊也不能加。
#include <iostream> #include <vector> #include <algorithm> #define maxn 10005 using namespace std; int n, m; namespace djs { int parent[maxn]; bool mark[maxn]; void init() { for (int i = 0; i <= n; i++) { parent[i] = -1; mark[i]= false; } } int find(int x) { if (parent[x] < 0) return x; else return parent[x] = find(parent[x]); } bool merge(int x, int y) { x = find(x); y = find(y); if (x != y) // x與y不在一個連通塊 { if (mark[x] && mark[y]) // 兩個連通塊都有環 return false; else { if (parent[x] > parent[y]) swap(x, y); parent[x] += parent[y]; parent[y] = x; mark[x] |= mark[y]; return true; } } else // x與y在一個連通塊 { if(mark[x]) return false; else // 這個連通塊沒有環,可以加這條邊 { mark[x] = true; return true; } } } } struct edge { int from, to, weight; }; inline bool cmper(const edge &x, const edge &y) { return x.weight > y.weight; } vector<edge> edges; int main() { while (true) { cin >> n >> m; if (n == 0 && m == 0) return 0; djs::init(); edges.clear(); int a, b, c; for (int i = 1; i <= m; i++) { cin >> a >> b >> c; edges.push_back((edge){a, b, c}); } sort(edges.begin(), edges.end(), cmper); int ans = 0; for (int i = 0; i < edges.size(); i++) { if (djs::merge(edges[i].from, edges[i].to)) ans += edges[i].weight; } cout << ans << endl; } return 0; }
【hdu3367】Pseudoforest(偽森林)