zoukankan      html  css  js  c++  java
  • HDU 2460 Network 边双连通分量 缩点

    题意:

    给出一个无向连通图,有(m)次操作,每次在(u, v)之间加一条边,并输出此时图中桥的个数。

    分析:

    先找出边双连通分量然后缩点得到一棵树,树上的每条边都输原图中的桥,因此此时桥的个数为树的节点个数减一。
    然后每次添加一条边,相当于将树上对应节点(u, v)之间的边都变为非桥的边。
    每次暴力修改每条边的标记即可,还想更快一点的话还可以用树链剖分加速。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <vector>
    using namespace std;
    
    const int maxn = 100000 + 10;
    const int maxm = 200000 + 10;
    
    struct Graph
    {
        vector<int> G[maxn];
    
        void init(int n) { for(int i = 1; i <= n; i++) G[i].clear(); }
    
        void AddEdge(int u, int v) { G[u].push_back(v); }
    };
    
    int n, m;
    Graph g, t;
    
    stack<int> S;
    int dfs_clock, pre[maxn], low[maxn];
    int scc_cnt, sccno[maxn];
    
    void dfs(int u, int fa) {
        pre[u] = low[u] = ++dfs_clock;
        S.push(u);
        bool flag = false;
        for(int v : g.G[u]) {
            if(v == fa && !flag) { flag = true; continue; }
            if(!pre[v]) {
                dfs(v, u);
                low[u] = min(low[u], low[v]);
            } else if(!sccno[v]) low[u] = min(low[u], pre[v]);
        }
    
        if(low[u] == pre[u]) {
            scc_cnt++;
            for(;;) {
                int x = S.top(); S.pop();
                sccno[x] = scc_cnt;
                if(x == u) break;
            }
        }
    }
    
    void find_scc() {
        dfs_clock = scc_cnt = 0;
        memset(pre, 0, sizeof(pre));
        memset(sccno, 0, sizeof(sccno));
        for(int i = 1; i <= n; i++) if(!pre[i])
            dfs(i, -1);
    }
    
    int bridges;
    int fa[maxn], dep[maxn];
    bool covered[maxn];
    
    void dfs2(int u) {
        for(int v : t.G[u]) {
            if(v == fa[u]) continue;
            dep[v] = dep[u] + 1;
            fa[v] = u;
            dfs2(v);
        }
    }
    
    void update(int u, int v) {
        if(dep[u] < dep[v]) swap(u, v);
        while(dep[u] > dep[v]) {
            if(!covered[u]) { covered[u] = true; bridges--; }
            u = fa[u];
        }
        while(u != v) {
            if(!covered[u]) { covered[u] = true; bridges--; }
            if(!covered[v]) { covered[v] = true; bridges--; }
            u = fa[u]; v = fa[v];
        }
    }
    
    int main()
    {
        int kase = 1;
        while(scanf("%d%d", &n, &m) == 2) {
            if(!n && !m) break;
            g.init(n);
            while(m--) {
                int u, v; scanf("%d%d", &u, &v);
                g.AddEdge(u, v);
                g.AddEdge(v, u);
            }
            find_scc();
    
            t.init(scc_cnt);
            for(int u = 1; u <= n; u++) {
                for(int v : g.G[u]) {
                    if(sccno[u] == sccno[v]) continue;
                    t.AddEdge(sccno[u], sccno[v]);
                }
            }
            dfs2(1);
    
            printf("Case %d:
    ", kase++);
    
            bridges = scc_cnt - 1;
            memset(covered, false, sizeof(covered));
            int q; scanf("%d", &q);
            while(q--) {
                int u, v; scanf("%d%d", &u, &v);
                update(sccno[u], sccno[v]);
                printf("%d
    ", bridges);
            }
            printf("
    ");
        }
    
        return 0;
    }
    
  • 相关阅读:
    Qt Quick之QML与C++混合编程详解
    Qt QML与C++混合编程
    Qt QML和QtQuick简介以及QML实例
    Qt 渐变 QLinearGradient、 QConicalGradient、QRadialGradient
    Qt 加载HeightMap(高度图)构造3D地形图
    VisionPro内嵌脚本编译时显示:未定义类型“CogFindCircleTool”。未定义类型“CogToolResultConstants”
    VisionPro CogPMAlignTool
    VisionPro 卡尺原理
    VisionPro 卡尺测量长度的例子
    VisionPro 自学帮助
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/5354318.html
Copyright © 2011-2022 走看看