Minimum Cut HDU

题意

给一张无向连通图和图上的一棵生成树。问至少删除几条边使图不连通,且满足删除的边有且仅有一条树边。

题解

若删除一条树边((u, v)),那么(u)(v)之间的非树边都要删除,这样就是一种方案。

如何计算(u)(v)之间的非树边呢?考虑对所有非树边,做树上差分(cnt[u_i])++, (cnt[v_i])++, (cnt[lca(u_i, v_i)]) -= (2)。那么若(v)(u)儿子节点,那么以(v)为根节点的子树(cnt)和就是答案。

故枚举所有的非树边((u, v)),更新答案最小值。最后答案不要忘了加上那一条树边。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e4 + 100;

int T, n, m, x, y, ans;
vector<int> V[maxn];
int cnt[maxn], dep[maxn];
int r[maxn][20];
int depth;


void build(int x, int y) {
    V[x].push_back(y);
    V[y].push_back(x);
}

int get_ans(int x, int from) {
    int res = cnt[x];
    for (auto y : V[x]) {
        if (y == from) continue;
        res += get_ans(y, x);
    }
    if (x != 1) ans = min(ans, res);
    return res;
}

void init_lca(int root=1) {

    queue<int> Q;
    Q.push(root);
    dep[root] = 1;
    while(!Q.empty()) {
        int x = Q.front(); Q.pop();
        for (auto y : V[x]) {
            if (dep[y]) continue;
            dep[y] = dep[x] + 1;

            r[y][0] = x;
            for (int j = 1; j <= depth; j++)
                r[y][j] = r[r[y][j-1]][j-1];
            Q.push(y);
        }
    }
}

int lca(int x, int y) {
    if (dep[x] > dep[y]) swap(x, y);

    for (int i = depth; i >= 0; i--)
        if (dep[r[y][i]] >= dep[x]) y = r[y][i];

    if (x == y) return x;

    for (int i = depth; i >= 0; i--)
        if (r[x][i] != r[y][i]) x = r[x][i], y = r[y][i];
    return r[x][0];
}

int main() {
    scanf("%d", &T);
    for (int ca = 1; ca <= T; ca++) {
        scanf("%d%d", &n, &m);

        for (int i = 1; i <= n; i++) V[i].clear();
        memset(cnt, 0, sizeof(cnt));

        for (int i = 1; i <= n-1; i++) {
            scanf("%d%d", &x, &y);
            build(x, y);
        }

        depth = (int)(log(n)/log(2)) + 1;
        init_lca();
        for (int i = n; i <= m; i++) {
            scanf("%d%d", &x, &y);
            int L = lca(x, y);
            cnt[x]++, cnt[y]++, cnt[L] -= 2;
        }

        ans = 0x3f3f3f3f;
        get_ans(1, 0);
        printf("Case #%d: %d
", ca, ans+1);
    }
}

原文地址:https://www.cnblogs.com/ruthank/p/11231948.html