zoukankan      html  css  js  c++  java
  • POJ

    题意:给一张无向图,有M次加边的操作,每次操作之后输出割边的数目。

    分析:显然,割边肯定出现在任意一棵生成树中,用数组f[u]记录点u在dfs树上的父亲节点,用这种方式就可以快速地找出dfs树上的任意一条边。在u,v之间加边后,原来的减去的割边肯定是u,v在dfs树上的最短路径中出现。那么每次操作之后,在求u,v两点lca的过程中,就可以判断减少了多少条割边。

    但O(n)地求lca效率上并不好,仍有改进的空间。在求lca的过程中,如果一条边确定不是割边,那么之后也没有访问它的必要,所以可以将其向上合并。

    并且在初始Tarjan求割边的过程中,就可将不是割边的边向上合并。

    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<cstring>
    using namespace std;
    const int maxn =1e5+5;
    struct Edge{
        int to,next;
    }edges[maxn*4];
    int pre[maxn],low[maxn],f[maxn],head[maxn],dfn,tot,top;
    bool judge[maxn];
    void init()
    {
        dfn=tot=top=0;
        f[1]=1;
        memset(pre,0,sizeof(pre));
        memset(low,0,sizeof(low));
        memset(head,-1,sizeof(head));
        memset(judge,0,sizeof(judge));
    }
    
    int Find(int x){ return f[x]==x? x:f[x] =Find(f[x]); }
    
    void Union(int u,int v)
    {
        int fu= Find(u);
        int fv = Find(v);
        if(fu!=fv){             //后向前并
            f[fv] =fu;
        }
    }
    
    void AddEdge(int u,int v)
    {
        edges[top].to =v;
        edges[top].next = head[u];
        head[u] = top++;
    }
    
    void Tarjan(int u,int fa,int id)            //id表示边的序号
    {
        f[u]=fa;
        pre[u] = low[u]= ++dfn;
        int v;
        for(int i=head[u];i!=-1;i=edges[i].next){
            v = edges[i].to;
            if(i==(id^1))   continue;   //实际上是一条边 没有访问的必要
            if(!pre[v]){
                Tarjan(v,u,i);
                low[u] = min(low[u],low[v]);
            }
            else
                low[u]=min(low[u],pre[v]);
            if(low[v]>pre[u]){              //割边
                tot++;
                judge[v]=true;
            }
            else
                Union(u,v);             //缩点
        }   
    }
    
    void LCA(int u,int v)
    {
        if(pre[v]<pre[u])
            swap(u,v);
        while(pre[v]>pre[u]){
            if(judge[v]){tot--;judge[v]=false;}
            v = f[v];
        }
        while(u!=v){
            if(judge[u]){tot--;judge[u]=false;}
            if(judge[v]){tot--;judge[v]=false;}
            u = f[u];
            v = f[v];
        }
    }
    
    int main()
    {
        int N,M,u,v,tmp,Q;
        int T=1;
        while(~scanf("%d%d",&N,&M),N+M){
            init();
            for(int i=0;i<M;++i){
                scanf("%d%d",&u,&v);
                AddEdge(u,v);
                AddEdge(v,u);
            }
            Tarjan(1,1,-1);
            printf("Case %d:
    ",T++);
            scanf("%d",&Q);
            for(int i=0;i<Q;++i){
                scanf("%d%d",&u,&v);        //选取low较小的点作为终点
                LCA(u,v);
                printf("%d
    ",tot);
            }
            printf("
    ");
        }   
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    python 计时累积超过24小时时继续往上累加
    linux 下获取文件最后几行
    unbuntu 安装python包提示E: Unable to locate package python-timeout
    python 计时器
    jquery中html()、text()、val()的区别
    DESC和 ACS
    jQuery自动截取文字长度,超过部分
    Spring MVC 注解
    注解笔记
    Spring Data JPA初使用 *****重要********
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9487392.html
Copyright © 2011-2022 走看看