首页 > 代码库 > bzoj 2654 tree
bzoj 2654 tree
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2654
题解:
若给每条白边加一个权值x,会使得选择白边的数量变少,即选择白边的数量f(x)单调递减,如此,二分x,使f(x)==need即可
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 #define MAXN 50010 5 #define MAXM 100010 6 int father[MAXN],n,m,cnt,ans1,ans,need,u[MAXM],v[MAXM],val[MAXM]; 7 bool col[MAXM]; 8 struct node 9 {10 int u,v,val;11 bool col;12 }edge[MAXM];13 void add(int a,int b,int c,int d,int i)14 {15 edge[i].u=a;16 edge[i].v=b;17 edge[i].val=c;18 edge[i].col=d;19 }20 int cmp(node a,node b)21 {22 return a.val==b.val?a.col<b.col:a.val<b.val;//排序时尽量把白边排在前面 23 }24 int find(int x)25 {26 if(father[x]==x)return x;27 else return father[x]=find(father[x]); 28 }29 bool Kruskal(int x)30 {31 ans1=cnt=0;//ans1为最小生成树权值和,cnt为所选白边数目 32 for(int i=1;i<=n;i++)father[i]=i;33 for(int i=1;i<=m;i++)34 {35 add(u[i],v[i],val[i],col[i],i);36 if(!edge[i].col)edge[i].val+=x;37 }38 sort(edge+1,edge+m+1,cmp);39 for(int i=1;i<=m;i++)40 {41 int a=find(edge[i].u);42 int b=find(edge[i].v);43 if(a==b)continue;44 else45 {46 father[b]=a;47 ans1+=edge[i].val;48 if(!edge[i].col)cnt++;49 }50 }51 return cnt>=need;52 }53 int main()54 {55 scanf("%d%d%d",&n,&m,&need);56 for(int i=1;i<=m;i++)scanf("%d%d%d%d",&u[i],&v[i],&val[i],&col[i]);57 int l=-100,r=100;58 while(l<=r)59 {60 int mid=(l+r)/2;61 if(Kruskal(mid))62 {63 l=mid+1;64 ans=ans1-mid*cnt;//总权值减去多加上的白边边权 65 }66 else r=mid-1;67 }68 printf("%d",ans);69 return 0;70 }
bzoj 2654 tree
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。