[bzoj2654][最小生成树][二分]tree
来源:互联网 发布:wkwebview 注入js代码 编辑:程序博客网 时间:2024/06/05 10:54
Description
给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。 题目保证有解。
Input
第一行V,E,need分别表示点数,边数和需要的白色边数。
接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。
Output
一行表示所求生成树的边权和。 V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。
Sample Input
2 2 1
0 1 1 1
0 1 2 0
Sample Output
2
题解
神题呐不会啊只能膜题解了。。
如果直接对原树进行kruskal的话,求出来的白边可能<need也可能>need的对不
那么怎么人为控制白边在树里的数目同时保证黑边选择最小呐?
还是最小生成树,只不过我们二分一个值mid,每次check的时候每条白边加上这个mid值,这样可以保证白边在生成树里一定是单调不下降或者单调不上升的,而这个时候的黑边同样有保证一定是最小的。
跑kruskal的时候判一下白边的边数,如果出来的边数>=need就是正确状态,那么树里的白边就需要减小,这时候mid往大的二分
小于need的情况就往小的二分
答案继承的时候需要减去mid*need这么多,因为白边至少都多了这么多的权嘛
一个特别的地方:题里可能有权相等的黑白边,这样kruskal排序的时候黑白边顺序是不定的。那这样跑出来的边数就可能小于need而wa掉。所以我们排序的时候当边权相等的时候再按颜色排,白色在前
#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;struct node{ int x,y,c,op;}a[211000],e[211000];int fa[111000];int findfa(int x){ if(fa[x]!=x)fa[x]=findfa(fa[x]); return fa[x];}int n,m,nd,cnt;bool cmp(node n1,node n2){ if(n1.c!=n2.c)return n1.c<n2.c; else return n1.op<n2.op;}bool chk(int p){ for(int i=1;i<=m;i++) { e[i]=a[i]; if(a[i].op==0)e[i].c+=p; } for(int i=1;i<=n;i++)fa[i]=i; sort(e+1,e+1+m,cmp); int tmp=n,op=0;cnt=0; for(int i=1;i<=m;i++) { int p=findfa(e[i].x),q=findfa(e[i].y); if(p!=q) { fa[p]=q; cnt+=e[i].c;tmp--; if(e[i].op==0)op++; if(tmp==1)break; } } if(op>=nd)return true; else return false;}int main(){ scanf("%d%d%d",&n,&m,&nd); for(int i=1;i<=m;i++){scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].c,&a[i].op);a[i].x++;a[i].y++;} int l=-150,r=150,ans; while(l<=r) { int mid=(l+r)/2; if(chk(mid)) { ans=cnt-nd*mid; l=mid+1; } else r=mid-1; } printf("%d\n",ans); return 0;}
阅读全文
0 0
- 【bzoj2654】【tree】【二分+最小生成树】
- 【二分+最小生成树】bzoj2654 tree
- bzoj2654 Tree 二分答案+最小生成树
- 【BZOJ2654】tree【二分】【最小生成树】
- bzoj2654 tree 最小生成树+二分验证
- [bzoj2654]tree 二分+最小生成树
- 【bzoj2654】【二分+最小生成树】tree
- [bzoj2654]tree(二分+最小生成树)
- 【二分+最小生成树】BZOJ2654[tree]题解
- 【二分+最小生成树】BZOJ2654 tree
- [bzoj2654][最小生成树][二分]tree
- bzoj2654: tree(二分+最小生成树)
- bzoj2654 二分+最小生成树
- bzoj2654 二分答案+最小生成树
- bzoj2654 tree(二分+kruskal)
- [WQS二分] BZOJ2654:tree
- bzoj2654 tree(kruskal+二分)
- BZOJ 2654 tree 二分+最小生成树
- Kotlin开发安卓APP笔记-条件语句和循环语句
- struts上传文件永久保存不丢失
- Next Greater Element I 比较
- 再谈Scala集合
- Linux设备驱动子系统第二弹
- [bzoj2654][最小生成树][二分]tree
- Shell脚本实现随机数多种方法介绍(date、random、uuid)
- 程序员口述:我是如何工作三年后跳槽到美团的?
- android 应用图标 角标 显示未读消息
- python之pprint模块简用
- can学习日志1
- JavaScript之事件的绑定与移除
- python3中,Tkinter中Canvas(画板)案例
- hdu 4052 线段树求面积并