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);
        }
    }
    
    
  • 相关阅读:
    java中获取类加载路径和项目根路径的5种方式分析
    浅谈HTTP中Get与Post的区别
    Http请求工具类 httputil
    Java中遍历数组的三种方式复习
    关于if else 和 三目运算符的效率问题-java
    EXCEL设置三级下拉框
    Java Web前端到后台常用框架介绍
    Shiro学习(总结)
    Shiro学习(24)在线回话管理
    使用jsr303实现数据校验
  • 原文地址:https://www.cnblogs.com/ruthank/p/11231948.html
Copyright © 2011-2022 走看看