zoukankan      html  css  js  c++  java
  • POJ3694:Network(并查集+缩点+lca)

    Network

    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 13172   Accepted: 4774

    题目链接:http://poj.org/problem?id=3694

    Description:

    A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are connected directly or indirectly by successive links, so data can be transformed between any two computers. The administrator finds that some links are vital to the network, because failure of any one of them can cause that data can't be transformed between some computers. He call such a link a bridge. He is planning to add some new links one by one to eliminate all bridges.

    You are to help the administrator by reporting the number of bridges in the network after each new link is added.

    Input:

    The input consists of multiple test cases. Each test case starts with a line containing two integers N(1 ≤ N ≤ 100,000) and M(N - 1 ≤ M ≤ 200,000).
    Each of the following M lines contains two integers A and B ( 1≤ A ≠ B ≤ N), which indicates a link between computer A and B. Computers are numbered from 1 to N. It is guaranteed that any two computers are connected in the initial network.
    The next line contains a single integer Q ( 1 ≤ Q ≤ 1,000), which is the number of new links the administrator plans to add to the network one by one.
    The i-th line of the following Q lines contains two integer A and B (1 ≤ A ≠ B ≤ N), which is the i-th added new link connecting computer A and B.

    The last test case is followed by a line containing two zeros.

    Output:

    For each test case, print a line containing the test case number( beginning with 1) and Q lines, the i-th of which contains a integer indicating the number of bridges in the network after the first i new links are added. Print a blank line after the output for each test case.

    Sample Input:

    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

    Sample Output:

    Case 1:
    1
    0
    
    Case 2:
    2
    0

    题意:

    首先给出一个无向图,然后不断加边,每次加一条边就输出当前图中桥有多少个。

    题解:

    首先单独计算桥很容易,但这个加边操作有点烦人,不可能每次加条边就求次桥吧。然后我们主要想的就是新边和原图的关系。

    因为原图是连通的,在原图中,我们很容易把桥求出来,并且将相应的点进行缩点(这里我用的并查集),最后的图中的边都为桥,且无向图变成了树。

    那么每次新加入一条边,如果它连接的为不在一个集合中的点,那么必然会影响到从u到v简单路径上面的桥;否则就不影响。

    下面关键就是求这个简单路径,由于这个题数据量较小,用个朴素的lca就行了,这里的lca没有用深度来,而是根据dfn,很好地利用了时间戳。

    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+5,M  = 2e5+5;
    int n,m,ans;
    int head[N];
    struct Edge{
        int u,v,next;
    }e[M<<1];
    int T,tot;
    int dfn[N],low[N],cut[N],f[N],pa[N];
    void adde(int u,int v){
        e[tot].u=u;e[tot].v=v;e[tot].next=head[u];head[u]=tot++;
    }
    void init(){
        T=0;tot=0;ans=0;
        memset(head,-1,sizeof(head));
        memset(cut,0,sizeof(cut));
        memset(dfn,0,sizeof(dfn));
        memset(pa,0,sizeof(pa));
        for(int i=0;i<=n;i++) f[i]=i;
    }
    int find(int x){
        return f[x]==x ? x : f[x]=find(f[x]);
    }
    void Union(int u,int v){
        int fx=find(u),fy=find(v);
        if(fx!=fy) f[fx]=fy;
        return ;
    }
    void Tarjan(int u,int pre){
        dfn[u]=low[u]=++T;
        int son=0;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(v==pre) continue ;
            if(!dfn[v]){
                pa[v]=u;
                Tarjan(v,u);
                low[u]=min(low[u],low[v]);
                if(low[v]>dfn[u]){
                    cut[v]=1;
                    ans++;
                }else Union(u,v);
            }else{
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
    int lca(int u,int v){
        if(dfn[u]<dfn[v]) swap(u,v);
        while(dfn[u]>dfn[v]){
            int fx=find(u),fy=find(pa[u]);
            if(fx!=fy){
                ans--;
                f[fx]=fy;
            }
            u=pa[u];
        }
        while(dfn[v]>dfn[u]){
            int fx=find(v),fy=find(pa[v]);
            if(fx!=fy){
                ans--;
                f[fx]=fy;
            }
            v=pa[v];
        }
        return ans ;
    }
    int main(){
        int cnt = 0;
        while(scanf("%d%d",&n,&m)!=EOF){
            if(n+m<=0) break ;
            cnt++;
            init();
            for(int i=1;i<=m;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                adde(u,v);adde(v,u);
            }
            Tarjan(1,-1);
            int q;
            printf("Case %d:
    ",cnt);
            scanf("%d",&q);
            while(q--){
                int u,v;
                scanf("%d%d",&u,&v);
                printf("%d
    ",lca(u,v));
            }
        }
        return 0;
    }
  • 相关阅读:
    《新土改:土地制度改革焦点难点辨析》:土地涨价要归公并用于城市配套设施,城市化的主角是人,小产权房不应该合法化,四星
    《清明上河图密码》:北宋的福尔摩斯探案,五星
    《中国的人口与城市》:关于中国人口与中国城市的数据分析,4星推荐。
    《集体失忆的黑暗时代》:已故加拿大公共知识分子关于城市规划与人类文明的随笔,三星推荐
    《智慧社会:大数据与社会物理学》:研究人类的想法的流动扩散的规律,四星
    《中国东部三大都市圈城市体系演化机制研究》:博士论文,结论是北上广深城市化规模还是不够,三星推荐
    《中国十亿城民——人类历史上最大规模人口流动背后的故事》:中国城市化将继续,城市对外来务工者应该更友好更包容,三星
    [Javascript] JavaScript赋值时的传值与传址
    [Vue @Component] Pass Props Between Components with Vue Slot Scope & renderless component
    [Dart] Understand Variables and Constants in Dart
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10393241.html
Copyright © 2011-2022 走看看