• Network HDU


    原题hdu链接 原题poj链接

    • 题解:做得比较通透的题,首先知道一条性质,边双连通分量缩点后会变成一棵树。要想知道加边后还有几个桥,那就相当于在一棵树上加边,找到这两个点的最近公共祖先,然后就可以找到经过了多少条边,这些全是桥,并且当经过后,这些桥都不再起作用了。
    • 代码:
    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <map>
    
    using namespace std;
    const int N = 101000;
    const int M = 401000;
    int h[M], ne[M], to[M], idx;
    int dfn[N], low[N], times;
    int stk[N], top;
    int id[N];
    int ans, e_dcc;
    int U[M], V[M];
    void add(int u, int v) {ne[idx] = h[u], to[idx] = v, h[u] = idx++;}
    void tarjan(int u, int from) {
        dfn[u] = low[u] = ++times;
        stk[++top] = u;
        bool flag = 1;
        for (int i = h[u]; i != -1; i = ne[i])
        {
            int v = to[i];
            if ((i^1) == from && flag) {flag = 0;continue;}
            if (!dfn[v]) {
                tarjan(v, i);
                low[u] = min(low[u], low[v]);
                if (low[v] > dfn[u]) {
                    ans++;
                }
            } else
                low[u] = min(low[u], dfn[v]);
        }
        if (low[u] == dfn[u]) {
            e_dcc++;
            while (1) {
                id[stk[top]] = e_dcc;
                if (stk[top--] == u)break;
            }
        }
    }
    int dep[N];
    int pre[N];
    bool bridge[N];
    void init() {
        memset(h, -1, sizeof h);
        memset(dfn, 0, sizeof dfn);
        memset(bridge, 0, sizeof bridge);
        memset(dep, 0, sizeof dep);
        idx = times = ans = e_dcc=top =0;
    }
    
    void dfs(int u, int fa) {
        if (fa == -1)dep[u] = 1;
        else dep[u] = dep[fa] + 1, pre[u] = fa;
        for (int i = h[u]; i != -1; i = ne[i]) {
            int v = to[i];
            if (dep[v] == 0)dfs(v, u);
        }
    }
    void lca(int x, int y) {
        if (dep[x] < dep[y])swap(x,y);
        while (dep[x] > dep[y]) {
            if (bridge[x])bridge[x] = 0,ans--;
            x = pre[x];
        }
        while (x != y) {
            if (bridge[x]) bridge[x] = 0, ans--;
            x = pre[x];
            if (bridge[y]) bridge[y] = 0, ans--;
            y = pre[y];
        }
    }
    void solve() {
        int n, m;
        int cas = 0;
    while (~scanf("%d%d", &n, &m)) {
        if (n == 0 && m == 0)break;
        init();
        for (int i = 1; i <= m; i ++) {
            scanf("%d%d", &U[i], &V[i]);int u = U[i],v = V[i];
            add(u, v);
            add(v, u);
        }
        for (int i = 1; i <= n; i ++) {
            if (!dfn[i])tarjan(i, -1);
            bridge[i]=1;
            dep[i] = 0;
        }
        memset(h, -1, sizeof h);idx = 0;
        for (int i = 1; i <= m; i ++) {
            int u = U[i], v = V[i];
            if (id[u] == id[v])continue;
            add(id[u], id[v]);
            add(id[v], id[u]);
        }
        dfs(1, -1);
        int q;scanf("%d", &q);
        printf("Case %d:
    ", ++cas);
        while (q--) {
            int u, v;scanf("%d%d", &u, &v);
            lca(id[u], id[v]);
            printf("%d
    ", ans);
        }puts("");
    }
    }
    int main() {
        int t = 1;//cin >> t;
        while (t--)solve();
        return 0;
    }
    
  • 相关阅读:
    『转』MySQL存储过程语法例子
    搭建mysql cluster
    C++ typedef 两种用法
    C++符号重载
    C++ int const 和 const int 的区别
    C++ 结构和类的区别
    正式开始jQuery源码的学习
    c# in deep 之Lambda表达式于LINQ表达式结合后令人惊叹的简洁(2)
    c# in deep 之Lambda表达式
    一道有意思的导论问题
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14632730.html
Copyright © 2020-2023  润新知