bzoj2654:木(バイナリ最小スパニング+)

タイトル

bzoj2654:ツリー

解決

kruscalプレスの重量は、最小スパニングツリー、我々は白側の右側を制御することにより、白側の数を制御することができますすることを選択する小さな重みをやってソート。
私たちは、白側を通って一定の値を与えることができるの半分を加えた答え
を同時に2つの点に注意を払います

  1. 白側に付加価値を減算することを忘れないでください
  2. ホワイトエッジ前のソート

コード

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

int n, m, num, need, ans, tot, sum, cnt;

int fa[N], head[N], w[N];

struct node {
    int u, v, w, col;
    bool operator <(const node &oth) const {
        return w == oth.w ? col < oth.col : w < oth.w;
    }
} e[N], tmp[N];

int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

int kruscal() {
    cnt = 0, sum = 0, ans = 0;
    for (int i = 1; i <= n; ++i) fa[i] = i;
    sort(e + 1, e + 1 + m);
    for (int i = 1; i <= m; ++i) {
        int x = find(e[i].u), y = find(e[i].v);
        if (x == y) continue;
        fa[x] = y;
        ans += e[i].w;
        if (!e[i].col) sum++;
        cnt++;
        if (cnt == n - 1) break;
    }
    return sum;
}

bool check(int x) {
    for (int i = 1; i <= m; ++i) {
        e[i] = tmp[i];
        if (!e[i].col) e[i].w += x;
    }
    return kruscal() >= need;
}

int main() {
    ios::sync_with_stdio(false);
    cin >> n >> m >> need;
    for (int i = 1, x, y, z, c; i <= m; ++i) {
        cin >> x >> y >> z >> c;
        e[i] = (node) {x + 1, y + 1, z, c};
        tmp[i] = (node) {x + 1, y + 1, z, c};
    }
    int l = -1000, r = 1000;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (check(mid)) l = mid + 1, tot = ans - need * mid;
        else r = mid - 1;
    }
    cout << tot;
    return 0;
}

おすすめ

転載: www.cnblogs.com/lykkk/p/11223011.html