bzoj2654 二分+最小生成树
2017-07-05 08:11
197 查看
题目戳这里:http://www.lydsy.com/JudgeOnline/problem.php?id=2654
我们知道对于一个最小生成树而言,它的白边权值越大,那么生成树中的白边个数越少,反之亦然。
所以我们每次二分一个值,给白边加上它,在做最小生成树判断是否大于所需要的,然后就可以二分来搞了。
我们知道对于一个最小生成树而言,它的白边权值越大,那么生成树中的白边个数越少,反之亦然。
所以我们每次二分一个值,给白边加上它,在做最小生成树判断是否大于所需要的,然后就可以二分来搞了。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define N 100005 using namespace std; int n,m,k,u ,v ,w ,c ; struct Edge{ int u,v,w,c; }; Edge e ; bool cmp(const Edge &a,const Edge &b){ if(a.w<b.w)return 1; else if(a.w==b.w){ if(a.c<b.c)return 1; else return 0; } else return 0; } int fa ,tot=0; int getfa(int u){ if(fa[u]==u)return u; else return fa[u]=getfa(fa[u]); } bool check(int val){ tot=0;int cnt=0,ans=0; for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=m;i++){ e[i].u=u[i],e[i].v=v[i],e[i].w=w[i],e[i].c=c[i]; if(!e[i].c)e[i].w+=val; } sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++){ int x=getfa(e[i].u),y=getfa(e[i].v); if(x==y)continue; cnt++;tot+=e[i].w;if(!e[i].c)ans++; if(cnt==n-1)break; fa[x]=y; } return ans>=k; } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&u[i],&v[i],&w[i],&c[i]); u[i]++;v[i]++; } int l=-110,r=110; while(l<r){ if(r-l==1){ if(check(r))l=r; else r=l; } int mid=(l+r)>>1; if(check(mid))l=mid; else r=mid-1; } printf("%d\n",tot-l*k); }
相关文章推荐
- 二分+最小生成树【bzoj2654】: tree
- 【BZOJ2654】tree【二分】【最小生成树】
- BZOJ 2654: tree 最小生成树+二分
- BZOJ 2654 tree(二分答案+最小生成树)
- 【二分+最小生成树】bzoj2654 tree
- bzoj 2654 tree (二分 + 最小生成树)
- 【bzoj2654】【二分+最小生成树】tree
- 【二分+最小生成树】BZOJ2654 tree
- bzoj2654: tree(二分+最小生成树)
- bzoj2654 二分答案+最小生成树
- bzoj 2654: tree 二分+最小生成树
- BZOJ 2654 tree - 二分+最小生成树
- 【bzoj2654】【tree】【二分+最小生成树】
- BZOJ 2654 二分+最小生成树
- [bzoj2654]tree(最小生成树+二分)
- 【二分+最小生成树】BZOJ2654[tree]题解
- BZOJ 2654 tree 详解(最小生成树 kruskal 二分)
- BZOJ 2654 tree 二分+最小生成树
- [bzoj2654][最小生成树][二分]tree
- BZOJ2654 tree 【二分 + 最小生成树】