zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    
    
  • 相关阅读:
    二柱子在线答题
    SWUST OJ(952)
    SWUST OJ (943)
    FileZilla 客户端连接 FlieZilla 服务器 连接成功读取目录列表却失败的解决办法
    串的模式匹配算法 ------ KMP算法
    lvalue require as increment operand
    c 语言连续输入字符型数据
    [pat]数素数
    [PAT]数字分类
    HDOJ_4540_威威猫系列故事——打地鼠
  • 原文地址:https://www.cnblogs.com/ruthank/p/11231948.html
Copyright © 2011-2022 走看看