51nod 1640 MST+二分

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1640

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
 一道最大生成树的题目,对于这个最大魔法链值,我们显然可以通过二分出来他的最小值,然后类似于最小生成树的贪心做法,我们从满足条件的权值最大的边开始运行kruskal,由于要求只能有N-1条魔法链,所以相当于是kruskal只不过将边倒序枚举。
 第一次直接把l=0,r=INT_MAX,结果T了最后一个点,无奈做了一些优化,找到最大最小值赋给l,r然后就A了。
 
不过后来看别人题解发现好像没人用二分,可以先求一遍kruskal找到最后加入的边的权值,这就使得最大权值最小了,然后在倒序求一遍kruskal,只要当前边权值不大于之前求得的那个值就好啦。
 1 #include<bits/stdc++.h>   //二分650ms 
 2 using namespace std;
 3 #define LL long long
 4 struct Edge
 5 {
 6     int u,v,w;
 7     bool operator<(const Edge &t)const{
 8     return w<t.w;
 9     }
10 }e[200005];
11 int f[100005];
12 int getf(int v){return f[v]==v?f[v]:f[v]=getf(f[v]);}
13 bool ok(int k,int N,int M)
14 {
15     for(int i=1;i<=N;++i) f[i]=i;
16     for(int i=0;i<M&&e[i].w<=k;i++){
17         int fu=getf(e[i].u),fv=getf(e[i].v);
18         if(fv!=fu){
19             N--;
20             f[fv]=fu;
21         }
22         if(N==1) return 1;
23     }
24     return 0;
25 }
26 int main()
27 {
28     int N,M,i,j,l=2147483647,r=0;
29     cin>>N>>M;
30     for(i=0;i<M;++i){
31         scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
32         l=min(l,e[i].w);
33         r=max(r,e[i].w);
34     }
35     sort(e,e+M);
36     LL ans=0;
37     while(l<r){
38         int mid=l+((r-l)>>1);
39         if(ok(mid,N,M)){
40            r=mid;
41         }
42         else{
43           l=mid+1;
44         }
45     }
46     for(int i=1;i<=N;++i) f[i]=i;
47     Edge e1{-1,-1,l};
48     int ed=upper_bound(e,e+M+1,e1)-e;
49     for(int i=ed;i>=0;--i){
50         if(e[i].w>l) continue;
51         int fu=getf(e[i].u),fv=getf(e[i].v);
52         if(fv!=fu){
53             ans+=e[i].w;
54             N--;
55             f[fv]=fu;
56         }
57         if(N==1) break;
58     }
59     printf("%lld\n",ans);
60     return 0;
61 }

 

 1 #include<bits/stdc++.h>  //300ms
 2 using namespace std;
 3 #define LL long long
 4 struct Edge
 5 {
 6     int u,v,w;
 7     bool operator<(const Edge &t)const{
 8     return w<t.w;
 9     }
10 }e[200005];
11 int f[100005];
12 int getf(int v){return f[v]==v?f[v]:f[v]=getf(f[v]);}
13 int ok(int k,int N,int M)
14 {
15     for(int i=1;i<=N;++i) f[i]=i;
16     for(int i=0;i<M;i++){
17         int fu=getf(e[i].u),fv=getf(e[i].v);
18         if(fv!=fu){
19             N--;
20             f[fv]=fu;
21         }
22         if(N==1) return i;
23     }
24     return -1;
25 }
26 int main()
27 {
28     ios::sync_with_stdio(false);
29     int N,M,i,j,l=2147483647,r=0;
30     cin>>N>>M;
31     for(i=0;i<M;++i){
32             cin>>e[i].u>>e[i].v>>e[i].w;
33     }
34     sort(e,e+M);
35     LL ans=0;
36     l=ok(1,N,M);
37     while(l<M&&e[l+1].w==e[l].w) l++;
38     for(int i=1;i<=N;++i) f[i]=i;
39     for(int i=l;i>=0;--i){
40         int fu=getf(e[i].u),fv=getf(e[i].v);
41         if(fv!=fu){
42             ans+=e[i].w;
43             N--;
44             f[fv]=fu;
45         }
46         if(N==1) break;
47     }
48     printf("%lld\n",ans);
49     return 0;
50 }

 

posted @ 2017-08-13 09:02  *zzq  阅读(282)  评论(0编辑  收藏  举报