51nod 1640 MST+二分
http://www.51nod.com/onlineJudge/questionCode.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
一道最大生成树的题目,对于这个最大魔法链值,我们显然可以通过二分出来他的最小值,然后类似于最小生成树的贪心做法,我们从满足条件的权值最大的边开始运行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 }