• poj3694 网络(板子题)


    题面

    给定一张N个点M条边的无向连通图,然后执行Q次操作,每次向图中添加一条边,并且询问当前无向图中“桥”的数量。

    输入格式

    输入包含多组测试数据。

    每组测试数据,第一行包含两个整数N和M。

    接下来M行,每行包含两个整数A和B,表示点A和点B之间有一条边,点的编号为1~N。

    接下来一行,包含整数Q。

    在接下来Q行,每行包含两个整数A和B,表示在A和B之间加一条边。

    当输入0 0时表示输入终止。

    输出格式

    每组数据第一行输出“Case x:”,其中x为组别编号,从1开始。

    接下来Q行,每行输出一个整数,表示一次询问的结果。

    每组数据输出完毕后,输出一个空行。

    数据范围

    1≤N≤100000
    N−1≤M≤200000,
    1≤A≠B≤N,
    1≤Q≤1000
    

    输入样例:

    3 2
    1 2
    2 3
    2
    1 2
    1 3
    4 4
    1 2
    2 1
    2 3
    1 4
    2
    1 2
    3 4
    0 0
    

    输出样例:

    Case 1:
    1
    0
    
    Case 2:
    2
    0
    

    题解

    就是套板子题, e-DCC缩点, 重建图, 在跑树上LCA, 运用并查集解体, 主要是细节

    #include <bits/stdc++.h>
    #define all(n) (n).begin(), (n).end()
    #define se second
    #define fi first
    #define pb push_back
    #define mp make_pair
    #define sqr(n) (n)*(n)
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i=(a);i>=(b);--i)
    #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> PII;
    typedef pair<ll, ll> PLL;
    typedef vector<int> VI;
    typedef double db;
    
    const int N = 1e5 + 5, M = 2e6 + 5;
    
    int n, m, _, k;
    int h[N], to[M << 1], ne[M << 1], tot;
    int hc[N], tc[M << 1], nc[M << 1], totc;
    int dfn[N], low[N], df, st[N], top;
    int ecc[M], ecnt, ans;
    int f[N][20], dep[N], t;
    int fa[N];
    bool edge[M << 1], flag;
    
    void add(int u, int v) {
        ne[++tot] = h[u]; to[h[u] = tot] = v;
    }
    
    void add_c(int u, int v) {
        nc[++totc] = hc[u]; tc[hc[u] = totc] = v;
    }
    
    void tarjan(int x, int bian) {
        dfn[x] = low[x] = ++df;
        st[++top] = x;
        for (int i = h[x]; i; i = ne[i]) {
            int y = to[i];
            if (!dfn[y]) {
                tarjan(y, i);
                low[x] = min(low[x], low[y]);
    
                if (dfn[x] < low[y]) edge[i] = edge[i ^ 1] = 1, ++ans;
            }
            else if (i != (bian ^ 1)) low[x] = min(low[x], dfn[y]);
        }
        if (low[x] == dfn[x]) {
            ++ecnt; fa[ecnt] = ecnt;
            while (1) {
                int y = st[top--];
                ecc[y] = ecnt;
                if (y == x) break;
            }
        }
    }
    
    void bfs(int s) {
        queue<int> q;
        q.push(s); dep[s] = 1;
        rep(i, 0, t) f[s][i] = 0;
    
        while (!q.empty()) {
            int x = q.front(); q.pop();
            for (int i = hc[x]; i; i = nc[i]) {
                int y = tc[i];
                if (dep[y]) continue;
                dep[y] = dep[x] + 1;
                f[y][0] = x;
    
                for (int j = 1; j <= t; ++j)
                    f[y][j] = f[f[y][j - 1]][j - 1];
    
                q.push(y);
            }
        }
    }
    
    int lca(int x, int y) {
        if (dep[x] > dep[y]) swap(x, y);
        per(i, t, 0)
            if (dep[f[y][i]] >= dep[x]) y = f[y][i];
    
        if (x == y) return x;
    
        per(i, t, 0)
            if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
    
        return f[x][0];
    }
    
    int find(int x) {
        if (x == fa[x]) return x;
        return fa[x] = find(fa[x]);
    }
    
    int main() {
        IOS;
        while (cin >> n >> m, n && m) {
            flag = (n == 1e5 && m == 2e5);
    
            cout << "Case " << ++_ << ":" << '
    ';
            tot = 1; totc = ecnt = df = 0;
            rep(i, 1, n) h[i] = dfn[i] = low[i] = dep[i] = 0;
            rep(i, 1, m) {
                int u, v; cin >> u >> v;
                if (u == v) continue;
                add(u, v); add(v, u);
            }
    
            top = 0, tarjan(1, 0);
            rep (i, 1, ecnt) hc[i] = 0;
            ans = ecnt - 1;
    
            rep(i, 2, tot) { //可能有重边
                int x = to[i ^ 1], y = to[i];
                if (ecc[x] == ecc[y]) continue;
                add_c(ecc[x], ecc[y]);
            }
    
            t = log2(ecnt - 1) + 1;
            bfs(1);
    
            cin >> m;
            rep(i, 1, m) {
                int x, y; cin >> x >> y;
                x = find(ecc[x]), y = find(ecc[y]);
                int z = lca(x, y);
    
                while (dep[x] > dep[z]) fa[x] = f[x][0], --ans, x = find(x);
                while (dep[y] > dep[z]) fa[y] = f[y][0], --ans, y = find(y);
                cout << ans << '
    ';
            }
            cout << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    localStorage用法
    es6写法
    div滚动条
    搜索框聚焦和失焦
    初步理解前端模块化开发
    clam安装
    div行高不确定,文字和图片居中
    html页面设置<span>的高度和宽度
    一款好用的wangEditor编辑器
    3月23 防360网页的示意图
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/13623683.html
Copyright © 2020-2023  润新知