标签:hdu3367
3 3 0 1 1 1 2 1 2 0 1 4 5 0 1 1 1 2 1 2 3 1 3 0 1 0 2 2 0 0
3 5
题意:这题的题意折腾了好久才懂,开始以为是求最多有一个环的最大联通分量,然后WA了,后来才知道是求多个分量的最大和,每个分量最多有一个环。
题解:边权从大到小排序,对于每条边的起点终点a、b有三种情况:
1、a、b分属两个环,此时a、b不能连接;
2、a、b其中一个属于环,此时将另一个连过去或者两个都不在环中,此时任意连;
3、a、b在同一集合,但该集合无环,此时连接a、b并生成环。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn 10002
#define maxm 100002
using std::sort;
struct Node{
int u, v, cost;
} E[maxm];
int pre[maxn];
bool Ring[maxn];
bool cmp(Node a, Node b){
return a.cost > b.cost;
}
int ufind(int k)
{
int a = k, b;
while(pre[k] != -1) k = pre[k];
while(a != k){
b = pre[a];
pre[a] = k;
a = b;
}
return k;
}
int greedy(int n, int m)
{
int ans = 0, i, u, v;
for(i = 0; i < m; ++i){
u = E[i].u; v = E[i].v;
u = ufind(u); v = ufind(v);
if(Ring[u] && Ring[v]) continue;
if(u != v){
if(Ring[v]) pre[u] = v;
else pre[v] = u;
ans += E[i].cost;
}else if(Ring[v] == false){
Ring[v] = true;
ans += E[i].cost;
}
}
return ans;
}
int main()
{
int n, m, a, b, c, i;
while(scanf("%d%d", &n, &m), n||m){
memset(pre, -1, sizeof(pre));
memset(Ring, 0, sizeof(Ring));
for(i = 0; i < m; ++i)
scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].cost);
sort(E, E + m, cmp);
printf("%d\n", greedy(n, m));
}
return 0;
}HDU3367 Pseudoforest 【并查集】+【贪心】,布布扣,bubuko.com
HDU3367 Pseudoforest 【并查集】+【贪心】
标签:hdu3367
原文地址:http://blog.csdn.net/chang_mu/article/details/38454997