【最小生成树变形】HDU 3367

题意:求最大的边权值的和

满足在一个连通图里最多有一个环

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define IN     freopen ("in.txt" , "r" , stdin);
#define OUT  freopen ("out.txt" , "w" , stdout);
typedef long long LL;
const int MAXN = 11111;//点数的最大值
const int MAXM = 111111;//边数的最大值
const LL INF = 1152921504;
int fa[MAXN],flag[MAXN];
struct node
{
    int u,v;
    LL cost;
}edge[MAXM];
bool cmp(node a,node b)
{
    return a.cost>b.cost;
}
void init()
{
    for(int i=0;i<MAXN;i++)
        fa[i]=i,flag[i]=0;
}
int find(int x)
{
    if(x==fa[x])
        return x;
    else
    {
        fa[x]=find(fa[x]);
        return fa[x];
    }
}
LL kruskal(int m)//flag 表示该点所在的连通图有无环
{
    init();
    LL res=0;
    for(int i=0;i<m;i++)
    {
        node e=edge[i];
        int fu=find(e.u),fv=find(e.v);
        if(fu!=fv)//在不同的连通图里
        {
            if(!flag[fu]&&!flag[fv])//两个连通图都没有环
                res+=e.cost,fa[fu]=fv;
            else if(!flag[fu])//其中一个有环
            {
                res+=e.cost;
                flag[fu]=1;
                fa[fv]=fu;
            }
            else if(!flag[fv])
            {
                res+=e.cost;
                flag[fv]=1;
                fa[fu]=fv;
            }
        }
        else if(!flag[fu])//在一个连通图里,且无环
        {
            res+=e.cost;
            flag[fu]=1;
        }
    }
    return res;
}
int main()
{
    int n,m;
   // IN;
    while(scanf("%d%d",&n,&m),n+m)
    {
        for(int i=0;i<m;i++)
            scanf("%d%d%I64d",&edge[i].u,&edge[i].v,&edge[i].cost);
        sort(edge,edge+m,cmp);
        printf("%I64d\n",kruskal(m));
    }
}


posted @ 2014-08-14 11:00  kewowlo  阅读(153)  评论(0)    收藏  举报