这样阴沉的天气持续下去,我们不免担心起他的健康。
51nod魔法学校近日开展了主题为“天气晴朗”的魔法交流活动。
N名魔法师按阵法站好,之后选取N - 1条魔法链将所有魔法师的魔力连接起来,形成一个魔法阵。
魔法链是做法成功与否的关键。每一条魔法链都有一个魔力值V,魔法最终的效果取决于阵中所有魔法链的魔力值的和。
由于逆天改命的魔法过于暴力,所以我们要求阵中的魔法链的魔力值最大值尽可能的小,与此同时,魔力值之和要尽可能的大。
现在给定魔法师人数N,魔法链数目M。求此魔法阵的最大效果。
 

输入

两个正整数N,M。(1 <= N <= 10^5, N <= M <= 2 * 10^5)

接下来M行,每一行有三个整数A, B, V。(1 <= A, B <= N, INT_MIN <= V <= INT_MAX)

保证输入数据合法。

输出

输出一个正整数R,表示符合条件的魔法阵的魔力值之和。

输入样例

4 6
1 2 3
1 3 1
1 4 7
2 3 4
2 4 5
3 4 6

输出样例

12

题解

先跑一遍最小生成树,获得树中的最大边权,再利用边权不超过最大边权的所有边重新构建最大生成树。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100009;
struct node{
    int x,y;
    ll v;
};
bool cmp1(node a,node b){
    return a.v<b.v;
}
int f[maxn],n,m,pos,cnt;
ll ans;
int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}
node NODE[2*maxn];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++)
        f[i]=i;
    for(int i=0;i<m;i++)
        scanf("%d%d%lld",&NODE[i].x ,&NODE[i].y,&NODE[i].v);
    sort(NODE,NODE+m,cmp1);
    for(int i=0;i<m;i++){
        int x=find(NODE[i].x);
        int y=find(NODE[i].y);
        if(x!=y){
            f[x]=y;
            pos=i;
            if(++cnt>=n-1)break;
        }
    }
    for(int i=0;i<=n;i++)
        f[i]=i;
    while(NODE[pos+1].v==NODE[pos].v&&pos<m)pos++;
    cnt=0;
    for(int i=pos;i>=0;i--){
        int x=find(NODE[i].x);
        int y=find(NODE[i].y);
        if(x!=y){
            f[x]=y;
            ans+=NODE[i].v;
            if(++cnt>=n-1)break;
        }
    }
    printf("%lld",ans);
    return 0;
 } 

 

posted on 2020-04-07 16:42  新望  阅读(132)  评论(0)    收藏  举报