bzoj 2654 tree
Posted jack_yyc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2654 tree相关的知识,希望对你有一定的参考价值。
题目大意:
一个无向带权图,每条边为黑或白(1/0)
求包含k条白边的最小生成树,保证有解
思路:
蛇皮题
高老师提醒了我们二分
就是二分+mst
我们二分一个权值,然后对于每个白边加上这个权值
这样就可以算出我们要取哪些白边
所以二分的范围要到负数
如果知道要取哪些白边和黑边,然后直接求出这个树的权值减去白边被加上的值
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<set> 8 #include<map> 9 #include<vector> 10 #include<stack> 11 #include<queue> 12 #define ll long long 13 #define inf 2147383611 14 #define MAXN 50100 15 using namespace std; 16 inline ll read() 17 { 18 ll x=0,f=1; 19 char ch;ch=getchar(); 20 while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} 21 while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();} 22 return x*f; 23 } 24 int n,m,k; 25 struct data 26 { 27 int from,to,val,col; 28 bool operator < (const data &a) const 29 { 30 return val<a.val; 31 } 32 }edge[MAXN*2],tmp[MAXN*2]; 33 int f[MAXN],ans,res; 34 int find(int x) {return x==f[x]?x:f[x]=find(f[x]);} 35 bool ok(int a,int b) 36 { 37 int fa=find(a),fb=find(b); 38 if(fa==fb) return 1; 39 else {f[fa]=fb;return 0;} 40 } 41 bool check(int x) 42 { 43 int cnt=0;res=0,ans=0; 44 for(int i=1;i<=n;i++) f[i]=i; 45 for(int i=1;i<=m;i++) {tmp[i]=edge[i];if(!tmp[i].col) tmp[i].val+=x;} 46 sort(tmp+1,tmp+m+1); 47 for(int i=1;i<=m;i++) 48 { 49 if(!ok(tmp[i].from,tmp[i].to)) {cnt++,ans+=tmp[i].val;if(!tmp[i].col) {res++;ans-=x;}} 50 if(cnt==n-1) break; 51 //cout<<x<<" "<<cnt<<" "<<ans<<endl; 52 } 53 //cout<<x<<" "<<res<<" "<<ans<<endl; 54 return res>=k; 55 } 56 int main() 57 { 58 n=read(),m=read(),k=read(); 59 for(int i=1;i<=m;i++) edge[i].from=read()+1,edge[i].to=read()+1,edge[i].val=read(),edge[i].col=read(); 60 int l=-101,r=101,mid; 61 while(l<r-1) 62 { 63 mid=(l+r)>>1; 64 if(check(mid)) l=mid; 65 else r=mid; 66 if(res==k) break; 67 } 68 printf("%d",ans); 69 }
以上是关于bzoj 2654 tree的主要内容,如果未能解决你的问题,请参考以下文章