zoukankan      html  css  js  c++  java
  • codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

    题目链接:

    http://codeforces.com/gym/100114

    Description

    The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either through a direct link, or through a chain of links, by relaying information from server to server. Current network setup enables communication for any pair of servers. The network administrator strives to maximize network reliability. Some communication links in the network were identified as critical. A failure on any critical link will split the network into disconnected segments. Company management responded to the administrator’s concerns and agreed to fund another communication link, provided that when the new link goes online the number of critical links will be minimized. Write a program that, given a network configuration, will pick a pair of servers to be connected by the new communication link. If several such pairs allow minimizing the number of critical links then any of them will be considered as a correct answer. Example. The following figure presents a network consisting of 7 servers and 7 communication links. Essential links are shown as bold lines. A new link connecting servers #1 and #7 (dotted line) can reduce the number of the critical links to only one

    Input

    The first line contains two space-delimited integer numbers n (the number of servers) and m (the number of communication links). The following m lines describe the communication links. Each line contains two space-delimited integers xi and yi, which define the IDs of servers connected by link number i. Servers are identified with natural numbers ranging from 1 to n.

    Output

    The output file should contain a single line with space-delimited integers x and y, the IDs of servers to be connected by the new link..

    Sample Input

    7 7 1 2 2 3 2 4 2 6 3 4 4 5 6 7

    Sample Output

    1 7

    HINT

    1 ≤ n ≤ 10 000; 1≤ m ≤ 100 000; 1 ≤ xi, yi ≤ n; xi ≠ yi.
     

    题意:

    给你一个无相图,加一条边,使得桥的个数最小化。

    题解:

    对原图缩点得到一颗树,求树的直径,把直径两端点连起来。

    代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<stack>
    using namespace std;
    
    const int maxn = 10000 + 10;
    
    struct Edge {
        int u,v,type;
        Edge(int u,int v,int type=0) : u(u),v(v),type(type) {}
    };
    
    vector<int> G[maxn];
    vector<Edge> egs;
    int n, m;
    
    void addEdge(int u, int v) {
        egs.push_back(Edge(u,v));
        G[u].push_back(egs.size() - 1);
    }
    
    int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
    stack<int> S;
    
    //无相图的边双联通分量 tarjan
    void dfs(int u) {
        pre[u] = lowlink[u] = ++dfs_clock;
        S.push(u);
        for (int i = 0; i < G[u].size(); i++){
            Edge& e = egs[G[u][i]];
            if (e.type == 1) continue;
            egs[G[u][i] ^ 1].type ^= 1;//针对无相图,要标记反向边
            if (!pre[e.v]) {
                dfs(e.v);
                lowlink[u] = min(lowlink[u], lowlink[e.v]);
            }
            else if (!sccno[e.v]) {
                lowlink[u] = min(lowlink[u],pre[e.v]);
            }
        }
        if (lowlink[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(sccno, 0, sizeof(sccno));
        memset(pre, 0, sizeof(pre));
        for (int i = 0; i < n; i++) if (!pre[i]) dfs(i);
    }
    
    vector<int> T[maxn];
    //缩点得到的桥构成的树
    void build_tree() {
        for (int i = 0; i < egs.size(); i++) {
            Edge& e = egs[i];
            if (e.type) continue;
            if (sccno[e.u] != sccno[e.v]) {
                T[sccno[e.u]].push_back(sccno[e.v]);
                T[sccno[e.v]].push_back(sccno[e.u]);
            }
        }
        //for (int i = 1; i <= scc_cnt; i++) {
        //    printf("%d:", i);
        //    for (int j = 0; j < T[i].size(); j++) {
        //        int v = T[i][j];
        //        printf("%d ", v);
        //    }
        //    printf("
    ");
        //}
    }
    
    //求树的直径
    void dfs2(int u,int fa,int d,int &dep,int &res) {
        if (dep < d) dep = d, res = u;
        for (int i = 0; i < T[u].size(); i++) {
            int v = T[u][i];
            if (v == fa) continue;
            dfs2(v, u, d + 1, dep, res);
        }
    }
    
    void init() {
        for (int i = 0; i < n; i++) G[i].clear(), T[i].clear();
        T[n].clear();
    }
    
    int main() {
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        scanf("%d%d", &n, &m);
        init();
        for (int i = 0; i < m; i++) {
            int u, v;
            scanf("%d%d", &u, &v),u--,v--;
            addEdge(u, v);
            addEdge(v, u);
        }
        find_scc();
        build_tree();
        int u, v, dep;
        dep=-1,dfs2(1, -1, 0, dep, u);
        dep=-1,dfs2(u, -1, 0, dep, v);
        int au, av;
        for (int i = 0; i < n; i++) {
            //printf("sccno[%d]:%d
    ", i,sccno[i]);
            if (sccno[i] == u) au = i + 1;
            if (sccno[i] == v) av = i + 1;
        }
        printf("%d %d
    ", au, av);
        return 0;
    }
  • 相关阅读:
    随机变量数学期望的一个实例
    Form 对象的集合
    并排两个对象对不齐如何解决
    打开PPT 提示安装,非要取消才能显示PPT
    ATL 工程下添加右击菜单
    uva 10273 Eat or Not to Eat?
    python3根据地址批量获取百度地图经纬度
    <数据挖掘导论>读书笔记4--其他分类技术
    <数据挖掘导论>读书笔记6关联分析的高级概念
    <数据挖掘导论>读书笔记5关联分析的基本概念和算法
  • 原文地址:https://www.cnblogs.com/fenice/p/5616910.html
Copyright © 2011-2022 走看看