• 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);
        }
    }
    
    
  • 相关阅读:
    POJ 1860
    Notepad++ 经常使用快捷键 (MEMO)
    SpringMVC现实
    krpano漫游加方向性3D声音(这篇文章已被移到krpano中国网站 krpano360.com)
    DFS PKU 1562
    Java中间(三十五)-----Java详细设置(一个):请指定初始容量设置
    HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online
    智课雅思词汇---二十五、-ate
    新东方雅思词汇---8.3、apt
    新东方雅思词汇---7.4、cap
  • 原文地址:https://www.cnblogs.com/ruthank/p/11231948.html
Copyright © 2020-2023  润新知