zoukankan      html  css  js  c++  java
  • Bridges Gym

    http://codeforces.com/gym/100712/attachments

    题意是给定一个无向图,要求添加一条边,使得最后剩下的桥的数量最小。

    注意到在环中加边是无意义的。

    那么先把环都缩成一个点,然后重新建立一颗树,找出树的直径就好。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 1e5 + 20;
    struct Edge {
        int u, v, tonext;
    }e[maxn * 2], tree[maxn * 2];
    int first[maxn], num;
    int first_tree[maxn], num_tree;
    void addEdge(int u, int v) {
        ++num;
        e[num].u = u, e[num].v = v, e[num].tonext = first[u];
        first[u] = num;
    }
    int DFN[maxn], low[maxn], when, st[maxn], top;
    int id[maxn], toSelid;
    bool vis[maxn];
    void tarjan(int cur, int fa) {
        DFN[cur] = low[cur] = ++when;  //时间戳
        st[++top] = cur; //进栈
        vis[cur] = true;
        for (int i = first[cur]; i; i = e[i].tonext) {
            int v = e[i].v;
            if (v == fa) continue;
            if (!DFN[v]) { //没访问过
                tarjan(v, cur);
                low[cur] = min(low[cur], low[v]);
            } else if (vis[v]) { // 访问过,而且还在栈里
                low[cur] = min(low[cur], DFN[v]);
            }
        }
        if (low[cur] == DFN[cur]) { //这个是强连通分量的根节点。
            ++toSelid;
            do {
                id[st[top]] = toSelid;      //块id
    //            sum[toSelId]++;        //id节点个数
    //            printf("%d ", st[top]);
                vis[st[top]] = false;
                top--;
            } while (cur != st[top + 1]);
    //        printf("
    ");
        }
    }
    
    void solveTarjan(int n) {
        memset(DFN, 0, sizeof DFN);
        memset(low, 0, sizeof low);
        memset(vis, 0, sizeof vis);
        when = top = toSelid = 0;
        for (int i = 1; i <= n; ++i) {
            if (!DFN[i]) tarjan(i, i);
        }
    }
    void addEdgeTree(int u, int v) {
        ++num_tree;
        tree[num_tree].u = u, tree[num_tree].v = v, tree[num_tree].tonext = first_tree[u];
        first_tree[u] = num_tree;
    }
    
    struct bfsnode {
        int cur, cnt;
        bfsnode(int _cur, int _cnt) {
            cur = _cur;
            cnt = _cnt;
        }
    };
    int tree_diameter(int begin, bool flag) {
        memset(vis, 0, sizeof vis);
        queue<struct bfsnode> que;
        while (!que.empty()) que.pop();
        que.push(bfsnode(begin, 0));
        vis[begin] = true;
        int to = begin, mx = 0;
        while (!que.empty()) {
            struct bfsnode t = que.front();
            que.pop();
            for (int i = first_tree[t.cur]; i; i = tree[i].tonext) {
                int v = tree[i].v;
                if (vis[v]) continue;
                vis[v] = true;
                que.push(bfsnode(v, t.cnt + 1));
                if (mx < t.cnt + 1) {
                    to = v;
                    mx = t.cnt + 1;
                }
            }
        }
        if (flag) return mx;
        else return to;
    }
    
    
    void work() {
        memset(first, 0, sizeof first);
        memset(first_tree, 0, sizeof first_tree);
        num = num_tree = 0;
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            addEdge(u, v);
            addEdge(v, u);
        }
        solveTarjan(n);
    //    for (int i = 1; i <= n; ++i) {
    //        cout << id[i] << " ";
    //    }
        for (int i = 1; i <= n; ++i) {
            for (int j = first[i]; j; j = e[j].tonext) {
                int v = e[j].v;
                if (id[i] == id[v]) continue;
                addEdgeTree(id[i], id[v]);
                addEdgeTree(id[v], id[i]);
            }
        }
        int res = tree_diameter(1, 0);
        int di = tree_diameter(res, 1);
        int ans = toSelid - di - 1;
        ans = max(ans, 0);
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        int t;
        scanf("%d", &t);
        while (t--) work();
        return 0;
    }
    View Code
  • 相关阅读:
    Collections集合工具类排序
    集合的学习
    gitee使用方法
    vue 首屏优化
    vue 配置多个路由别名
    vue中的状态管理Vuex
    【Python】Pandas合并表格之(append, join , concat方法)
    elementui中提交表单自动刷新页面的问题
    滴滴实习面试题
    CSS 日常积累
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6652960.html
Copyright © 2011-2022 走看看