[bzoj2654]tree(二分+最小生成树)
2017-09-26 16:44
148 查看
题目:
我是超链接题解:
一开始博主想要把黑白边分开,然后sort,选择前need小的白边连起来,然后再连黑边但这个贪心是不对的,因为黑边的大小不确定,如果目前选择了较小的白边,可能会选上更大的黑边
问题的关键在于求出的最小生成树不一定含有need条白边
1、如果白边 > need条,我们需要“拖累”白边,让ta不要加进去那么多,你光拖白边A,不拖白边B就很不公平啊,所以要拖累就把所有的白边全都拖累上
2、如果白边 < need条,我们需要“帮助”这些白边,让ta加进去的更多一些,那就给ta们全都减去一个值
我们到底是帮助还是拖累呢?具体帮多少呢?我们可以运用二分!
你可以发现这是单调的:你加入的值越多,可以加入的白边就越少;反之亦然
那就走起?最后的答案就是 sum-你添加的总值
下面是一些小细节:
当有一种情况,mid+1加入的白边少1,mid加入的白边多1,这要怎么办呢?这样的情况只会出现于一些白边和黑边的权值相等,我们在排序的时候,权值相等的白边在先就OK啦
以下为博主口胡,即使不注意这个,你依然可以过这道题
但你的程序不一定是对的,试一下(卡掉学姐的)这组数据
3 3 1
0 1 4 1
0 2 2 0
1 2 2 0
ans=6
一个小问题:你的ans值什么时候修改呢?我们说你不能对于ans取min值(why?)
如果你把这个语句(ans=min(ans,sum-need*mid))放在[选的白边小于need]的后面,你就不怕一上来白边就小于mid,选了一棵正常的最小生成树,以后的权值肯定不会被修改
如果你把这个语句放在[选的白边大于need]的后面,你就不怕一上来白边大于mid,就同上了(hack了学姐。。。)
事实上可以证明当我们限定白边的数量一定的时候,答案也是唯一的
可以避免这个问题:只有在白点相等的时候再修改ans值
但是这样的答案是错的?
为什么呢?因为这道题的题目是错的,ta其实想让你求让你求一棵最小权的至少有need条白色边的生成树。
发现这个问题之后,以上就全部是博主的自我揣测了
代码:
#include <cstdio> #include <algorithm> #include <cstring> #define INF 1e9 using namespace std; struct hh{int x,y,c,col;}e[100005],b[100005]; int f[50005],n,m,ne,sum; int cmp(hh a,hh b){if (a.c==b.c)return a.col<b.col;else return a.c<b.c;} int find(int x) { if (f[x]!=x) f[x]=find(f[x]); return f[x]; } int check(int mid) { int i,tot=0,size=0;sum=0; for (i=0;i<n;i++) f[i]=i; for (i=1;i<=m;i++) { b[i]=e[i]; if (e[i].col==0) b[i].c+=mid; } sort(b+1,b+m+1,cmp); for (i=1;i<=m;i++) { int a=find(b[i].x),c=find(b[i].y); if (a!=c) { f[a]=c; tot++;sum+=b[i].c; if (!b[i].col) size++; } if (tot==n-1) break; } return size; } int main() { int i,ans=INF; scanf("%d%d%d",&n,&m,&ne); for (i=1;i<=m;i++) scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].c,&e[i].col); int l=-100,r=100; while (l<=r) { int mid=(l+r)>>1; if (check(mid)<ne) r=mid-1;//加入的边太少了,需要减的值很多啊 else l=mid+1,ans=sum-mid*ne; } printf("%d",ans); }
相关文章推荐
- BZOJ 2654 tree 二分+最小生成树
- 【二分+最小生成树】BZOJ2654[tree]题解
- BZOJ 2654: tree 最小生成树+二分
- BZOJ2654 tree 【二分 + 最小生成树】
- 二分+最小生成树【bzoj2654】: tree
- 【bzoj2654】【二分+最小生成树】tree
- [bzoj2654][最小生成树][二分]tree
- bzoj2654: tree(二分+最小生成树)
- BZOJ 2654 tree - 二分+最小生成树
- 【二分+最小生成树】BZOJ2654 tree
- bzoj 2654: tree 二分+最小生成树
- BZOJ 2654 tree 详解(最小生成树 kruskal 二分)
- 【bzoj2654】【tree】【二分+最小生成树】
- bzoj 2654 tree (二分 + 最小生成树)
- BZOJ 2654 tree(二分答案+最小生成树)
- 【二分+最小生成树】bzoj2654 tree
- bzoj 2654: tree (二分+最小生成树)
- [bzoj2654]tree(最小生成树+二分)
- [bzoj2654]tree 二分+最小生成树
- 【BZOJ2654】tree【二分】【最小生成树】