【BZOJ】2654 tree 二分+kruskal
2017-10-30 14:27
411 查看
题目传送门
好神的想法啊……这个二分好迷啊……
我们可以二分一个值mid,把所有白色的边都加上这个值,在最后计算边权和时减回去,也就相当于改变的白色边的优先级。
然后刷kruskal,如果mst中的白色边数不小于给定的need则验证成功,修改二分的边界继续二分。
附上AC代码:
好神的想法啊……这个二分好迷啊……
我们可以二分一个值mid,把所有白色的边都加上这个值,在最后计算边权和时减回去,也就相当于改变的白色边的优先级。
然后刷kruskal,如果mst中的白色边数不小于给定的need则验证成功,修改二分的边界继续二分。
附上AC代码:
#include <cstdio> #include <cctype> #include <algorithm> using namespace std; const int N=5e4+10; struct note{ int x,y,w,c; bool operator < (const note lyf) const {return w==lyf.w?c<lyf.c:w<lyf.w;} }a[N<<1],s[N<<1]; int n,m,k,sum,cnt,f ,l,r,mid,ans; inline char nc(void){ static char ch[100010],*p1=ch,*p2=ch; return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++; } inline void read(int &a){ static char c=nc();int f=1; for (;!isdigit(c);c=nc()) if (c=='-') f=-1; for (a=0;isdigit(c);a=(a<<3)+(a<<1)+c-'0',c=nc()); return (void)(a*=f); } inline int gf(int x){return x==f[x]?x:f[x]=gf(f[x]);} inline bool check(int mid){ sum=cnt=0; for (int i=1; i<=n; ++i) f[i]=i; for (int i=1; i<=m; ++i) s[i]=a[i],s[i].c==0?s[i].w+=mid:0; sort(s+1,s+1+m); for (int i=1; i<=m; ++i){ int fx=gf(s[i].x),fy=gf(s[i].y); if (fx!=fy){ f[fx]=fy,sum+=s[i].w; if (!s[i].c) ++cnt; } } return cnt>=k; } int main(void){ read(n),read(m),read(k); for (int i=1; i<=m; ++i) read(a[i].x),read(a[i].y),read(a[i].w),read(a[i].c),++a[i].x,++a[i].y; l=-105,r=105; while (l<r) if (check(mid=l+r>>1)) l=mid+1,ans=sum-k*mid; else r=mid-1; printf("%d\n",ans); return 0; }
相关文章推荐
- [BZOJ2654]tree(二分+Kruskal)
- [BZOJ2654][tree][二分+Kruskal]
- bzoj2654 tree(二分+kruskal)
- BZOJ 2654: tree kruskal 二分
- BZOJ[2654]Tree 二分+Kruskal
- BZOJ 2654 tree 二分答案+Kruskal
- [bzoj2654]tree_二分_kruskal
- BZOJ 2654 tree 详解(最小生成树 kruskal 二分)
- bzoj 2654: tree 二分+最小生成树
- [BZOJ 2654] tree · 二分答案
- bzoj2654: tree(二分+最小生成树)
- BZOJ 2654 tree(二分答案+并查集)
- [bzoj2654]tree(最小生成树+二分)
- [bzoj2654][最小生成树][二分]tree
- 【BZOJ2654】tree【二分】【最小生成树】
- bzoj 2654: tree (二分+最小生成树)
- 【二分+最小生成树】bzoj2654 tree
- 【bzoj2654】【二分+最小生成树】tree
- [bzoj2654]tree(二分+最小生成树)
- 二分+最小生成树【bzoj2654】: tree