给出一些边,每个边有一个边权和颜色。现在要求出最小边权有need个白边的生成树。输出这个边权。
在白边上加一个权值,这样就可以人为的改变白边出现在最小生成树。这个东西显然可以二分。之后取一下最小值就可以了。
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
using namespace std;
struct Edge{
int x, y, length, col;
bool operator <(const Edge &a)const {
if(length == a.length)
return col > a.col;
return length < a.length;
}
void Read() {
scanf("%d%d%d%d", &x, &y, &length, &col);
++x, ++y;
col ^= 1;
}
}edge[MAX];
int points, edges, need;
int father[MAX];
int Find(int x)
{
if(father[x] == x) return x;
return father[x] = Find(father[x]);
}
inline pair<int, int> MST()
{
for(int i = 1; i <= points; ++i)
father[i] = i;
pair<int, int> re(0, 0);
sort(edge + 1, edge + edges + 1);
for(int i = 1; i <= edges; ++i) {
int fx = Find(edge[i].x), fy = Find(edge[i].y);
if(fx != fy) {
father[fy] = fx;
re.second += edge[i].col;
re.first += edge[i].length;
}
}
return re;
}
int main()
{
cin >> points >> edges >> need;
for(int i = 1; i <= edges; ++i)
edge[i].Read();
int l = -110, r = 110, ans;
while(l <= r) {
int mid = (l + r) >> 1;
for(int i = 1; i <= edges; ++i)
edge[i].length += edge[i].col * mid;
int white = MST().second;
for(int i = 1; i <= edges; ++i)
edge[i].length -= edge[i].col * mid;
if(white >= need)
l = mid + 1, ans = mid;
else
r = mid - 1;
}
for(int i = 1; i <= edges; ++i)
edge[i].length += edge[i].col * ans;
cout << MST().first - need * ans << endl;
return 0;
}
原文地址:http://blog.csdn.net/jiangyuze831/article/details/44679751