51 NOD1640

1640 天气晴朗的魔法 

http://www.51nod.com/Challenge/Problem.html#!#problemId=1640

题目来源: 原创

基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题

这样阴沉的天气持续下去,我们不免担心起他的健康。

 

51nod魔法学校近日开展了主题为“天气晴朗”的魔法交流活动。

 

N名魔法师按阵法站好,之后选取N - 1条魔法链将所有魔法师的魔力连接起来,形成一个魔法阵。

 

魔法链是做法成功与否的关键。每一条魔法链都有一个魔力值V,魔法最终的效果取决于阵中所有魔法链的魔力值的和。

 

由于逆天改命的魔法过于暴力,所以我们要求阵中的魔法链的魔力值最大值尽可能的小,与此同时,魔力值之和要尽可能的大。

 

现在给定魔法师人数N,魔法链数目M。求此魔法阵的最大效果。

Input

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

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

保证输入数据合法。

Output

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

Input示例

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

Output示例

12

 

分析: 这是一个最小生成树的题,通过Kurstal算法 先求出 最小生成树的  最大的权值,

           然后 再把边 按权值从大到小排序,求出  最大权值和

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Node{
 int u ,v, w;
} eg[200005];
int  father[200010];
int  cmp1(const Node a, const Node b){ //按权值从小到大排序 
     return a.w < b.w;
}
int  cmp2(const Node a, const Node b){ //按权值从大到小排序  
     return a.w > b.w;
} 
int find( int x ){
	return father[x] == x ? x : father[x] = find( father[x] );
}
void merge( int x ,int y ){
	 int fx = find( x );
	 int fy = find( y );
	 if( fx != fy ){
	 	 father[fx] = fy;
	 } 
}
void init( int n  ){
	  for( int i=0;i<=n;i++)
	       father[i] = i; 
} 
int  main(void){ 
 int a,b,n,M;
 scanf("%d%d",&n,&M);
 for( int i=0;i <M ; i++ ) 
      scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].w);
 
 // 从小到大排序 
 sort(eg,eg+M,cmp1);
 //  跑最小生成树算法 ,
 // 求出能生成最小生成树的情况下,求其中 单条魔法链的 最大权值  
 init(n); // 先初始化,父亲节点
 int maxx = -1; 
 for( int i=0;i<M;i++){ //找最小生成树 
 	  a = eg[i].u;
 	  b = eg[i].v;
 	  if( find(a) != find(b) ){ 
	      if( eg[i].w > maxx ){
 	  	      maxx = eg[i].w;
	      }
	      merge(a,b);
      }
 }  
 // 在能生成最小生成树的条件下, 求最大权值之和 
 long long int ans = 0;
 init(n);
 sort(eg,eg+M,cmp2); // 按权值从大到小排序 
 for( int i=0;i<M;i++){ //找最小生成树 
 	  a = eg[i].u;
 	  b = eg[i].v;
 	  if( find(a) != find(b) ){ 
	      if( eg[i].w <=  maxx ){
 	  	      merge(a,b);
              ans+=eg[i].w;  
 	  	  }
      }
 } 
 printf("%lld\n",ans);
 return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值