HDU 3367 Pseudoforest

来源:互联网 发布:flash ftp软件绿色版 编辑:程序博客网 时间:2024/05/18 00:51

题意:给你n,m。m条边,找出一颗最多带一个环的权值最大的子树。

思路:模仿生成树的都建方法,用并查集一条边一条边的连起来,用vis[]数组判一下,这棵树是否带环即可。代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>using namespace std;typedef long long LL;const int maxn = 100000 + 7;int n, m, pa[maxn];bool vis[maxn];struct Node {    int u, v, d;    bool operator < (const Node& a) const {        return d > a.d;    }}G[maxn];int Find(int x) {    if(pa[x] == x) return x;    else return pa[x] = Find(pa[x]);}int main() {    while(~scanf("%d%d", &n, &m)) {        LL ans = 0;        if(!n && !m) break;        for(int i = 0; i <= n; ++i) pa[i] = i;        memset(vis, false, sizeof(vis));        for(int i = 0; i < m; ++i) scanf("%d%d%d", &G[i].u, &G[i].v, &G[i].d);        sort(G, G+m);        for(int i = 0; i < m; ++i) {            int x = Find(G[i].u);            int y = Find(G[i].v);            if(x != y) {                if(vis[x] && vis[y]) continue; //x和y树都带坏,不能合并                if(vis[x] || vis[y]) vis[x] = vis[y] = true; //有一个带环,则合起来,就带环                ans += G[i].d;                pa[x] = y;            }            else if(!vis[x]) { //如果没有环,则找出一条,(显然,有环的树的总权值比没有换的树的总权值要大)                vis[x] = true;                ans += G[i].d;                if(x == y) continue;                pa[x] = y;            }        }        printf("%lld\n", ans);    }}


0 0
原创粉丝点击