题目链接
题意,给你一个无向图,边分黑白,而且有权值。固定使用k个白边,n-1-k个黑边。问:最小生成树。
题解:
不看题解,再给本憨批800年也想不出这种解法。首先说做法:我们把所有白边都加上一个值C(可为负数),则此时显然在排序后白边的位置会整体往前/后”偏移“一段距离。我们二分C的值,然后求最小生成树,直到而分出一个刚好用k条白边的情况。这个最小生成树的值即为所求。
粗略证明:
此部分证明是我自己推定的,,,可能会有错误,酌情参考
首先考虑最小生成树,但是这时白边的数量可能不符合要求。假定现在白边选多了,我们就试图把所有的白边权值加上一个值C,显然可能会导致白边的数量减少。因为,我们在给白边加值的时候,会导致一些白边被换到某些黑边后面,也就是说,再考虑这条白边的时候,会优先考虑被换过的黑边。这样做是不是最优的?也就是说会不会存在这么一个生成树:把二分的结果(即使用了k条白边的结果)中,个别白边先前或者向后移动,得到的最小生成树,它仍可以保证使用K条白边,而且比整体+C所产生的生成树权值要小。——答案是不存在的,
此时存在两种情况:
(1)一个没有被选的白边向前移动后被选中了。
(2)一个被选中的白边向后移动被黑边枪了位置。
先看第一种情况:
首先说一个引理:
根据kruskal算法性质,在考虑到第i条时,只要保证前i条边集合是不考虑权值相同的,那么此时图的联通性一样。
这点在最小生成树计数有应有。
所有如果我们考虑第i个边,如果它是一条白边,我们把它的位置先前移动,到了第j位置,那么此时,考虑前i条边,因为考虑的边集没有发生变化,所有在考虑完前i条边时,图的联通性没有发生改变。所有对于从i+1到m的边,我们的选择不会发生改变。而对于1到j-1的边,显然我们的选择不会发生改变,而对于区间j到i的边,我们产生了如下改变:多选了一个白边,少选了一个黑边。显然此时,白边选了k+1个,不合要求。
同理可判第二中情况不符合要求。
ps.如果你是在中石油大学oj上交题,请注意,中石油大学oj时限奇短(HDU此题时限为15s,石油大学是1s),以至于 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)的算法是被卡掉的。所有每次二分要把里面的排序提到外面来。 O ( n l o g n ) O(nlogn) O(nlogn)可以过,但是700+ms。注意常数!
下面是ac代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include <map>
#include <queue>
#include <set>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <bitset>
#include <array>
#include <cctype>
#include <time.h>
#pragma GCC optimize(2)
void read_f() {
freopen("1.in", "r", stdin); freopen("1.out", "w", stdout); }
void fast_cin() {
std::ios

最低0.47元/天 解锁文章
1580

被折叠的 条评论
为什么被折叠?



