HDU 3367 Pseudoforest (最大生成树)

时间:2021-08-02 11:14:12

题意:给出一个图,要求出最大的pseudoforest, 所谓pseudoforest就是指这个图的一个子图,这个子图的每个连通分量中最多只能有一个环,

而且这个子图的所有权值之和最大。这个就是所谓的伪森林。

析:并查集,在比赛时,做了3个多小时,都没做出来,就是题意没读对,我以为就是最大生成树,但其实并不是这样的,可以不是树,是森林。。。。。

那么我们就要去想想了,先确实两个端点是不是在同一个环里,再判断是不是各自在一个环里,再判断是不是有一个在环里,然后依次做出相应的计算即可。

如果在一个环,或者是在各自环,那么就舍弃,如果有一个在环里,就标记,如果全不是而又形成环了,就标记,否则不标记。

代码如下:

#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
using namespace std ;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 1e4 + 5;
const int INF = 0x3f3f3f3f;
struct node{
    int u, v, c;
    node(int uu = 0, int vv = 0, int cc = 0) : u(uu), v(vv), c(cc) { }
    bool operator < (const node &p) const{
        return c > p.c;
    }
};
node a[maxn*10];
int p[maxn];
int vis[maxn];
int Find(int x){  return x == p[x] ? x : p[x] = Find(p[x]); }

int main(){
    int n, m;
    while(scanf("%d %d", &n, &m)){
        if(!m && !n)  break;
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; ++i)  p[i] = i;
        for(int i = 0; i < m; ++i){
            int u, v, c;
            scanf("%d %d %d", &u, &v, &c);
            a[i] = node(u+1, v+1, c);
        }

        sort(a, a+m);
        int ans = 0;
        for(int i = 0; i < m; ++i){
            int x = Find(a[i].u);
            int y = Find(a[i].v);
            if(x == y){
                if(!vis[x] && !vis[y]){
                    ans += a[i].c;
                    vis[x] = vis[y] = 1;
                    p[y] = x;
                }
            }
            else{
                if(!vis[x] && !vis[y]){
                    ans += a[i].c;
                    p[y] = x;
                }
                else if(!vis[x] || !vis[y]){
                    ans += a[i].c;
                    vis[x] = vis[y] = 1;
                    p[y] = x;
                }
            }
        }

        cout << ans << endl;
    }
    return 0;
}