zoukankan      html  css  js  c++  java
  • HDU 2460 Network(tarjan边双联通)

    HDU 2460 Network

    题意

    给一个连通无向图,在这个图的基础上给出一些连边的操作,问每次操作后还剩多少个桥?
    

    思路

    首先跑一次tarjan不用说,这里尤注意与求scc的tarjan不同,关于桥的判断,要在dfs
    结束回溯的时候直接if(low[v]>dfn[u])判断。
    

    然后对于每一个操作,判断要加的两个点在不在一个双连通分量,
    如果在一个双连通分量里面,不用进行任何操作(这样加边不会减少桥);
    如果不在一个双连通分量里面,就会形成新的环,这个时候把两点之间的路径上的桥的标记全部去掉即可。
    (注意代码中“边权下放”的思想)。
    所谓“边权下放”的思想,我认为,是把本来以边为下标存储的信息变成以点为下标的思想。
    

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<stack>
    #include<vector>
    using namespace std;
    const int maxn=100000+10,maxm=200000+10;
    stack<int> s;
    vector<int> G[maxn];
    //struct edge{
    //  int v,next;
    //}a[maxm];
    //int h[maxn],tot;
    /*void add_e(int x,int y){
        a[tot].v=y;
        a[tot].next=h[x];
        h[x]=tot++;
    }*/
    int dfn[maxn],low[maxn],isBri[maxn],belong[maxn],father[maxn];
    int dfs_clock,cnt_bri;
    //int f[maxn][25],dep[maxn];
    void dfs(int u,int fa){
        father[u]=fa;
        low[u]=dfn[u]=++dfs_clock;
        s.push(u);
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
    //      if(i/2==fa/2&&fa!=-1)continue;
            if(v==fa)continue;
            if(!dfn[v]){
    //          dfs(v,i);
                dfs(v,u);
                low[u]=min(low[u],low[v]);
                if(low[v]>dfn[u]){
                    isBri[v]=1;//“边权下放” 
                    cnt_bri++;
                    int x;
                    do{
                        x=s.top();s.pop();
                        belong[x]=cnt_bri;
                    }while(x!=v);
                }
            }else{
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
    /*void dfs2(int u,int fa){
        dep[u]=dep[fa]+1;
        f[u][0]=fa;
        for(int i=1;i<=20;i++)
            f[u][i]=f[f[u][i-1]][i-1];
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==fa)continue;
            dfs2(v,u);
        }
    }*/
    /*int lca(int x,int y){
        if(dep[x]<dep[y])
            swap(x,y);
        int dc=dep[x]-dep[y];
        for(int i=0;i<=20;i++){
            if((1<<i)&dc)
                x=f[x][i];
        }
        if(x==y)return x;
        for(int i=20;i>=0;i--){
            if(f[x][i]!=f[y][i]){
                x=f[x][i];
                y=f[y][i];
            }
        }
        return f[x][0];
    }*/
    /*void mark(int u,int goal){
        while(u!=goal){
            if(isBri[u]){
                cnt_bri--;
                isBri[u]=0;
            }
            u=f[u][0];
        }
    }*/
    void func(int x,int y){
        while(x!=y){
            if(isBri[x]){
                isBri[x]=0;
                cnt_bri--;
            }
            if(isBri[y]){
                isBri[y]=0;
                cnt_bri--;
            }
            x=father[x];
            y=father[y];
        }
    }
    int main(){
    //  freopen("JJJ.in","r",stdin);
        int n,m,kase=0;
        while(scanf("%d%d",&n,&m)==2&&(n+m)){
            kase++;
            printf("Case %d:
    ",kase);
    //      tot=0;
    //      memset(h,-1,sizeof h);
            for(int i=1;i<=n;i++)
                G[i].clear();
            for(int i=1;i<=m;i++){
                int x,y;
                scanf("%d%d",&x,&y);
    //          add_e(x,y);
    //          add_e(y,x);
                G[x].push_back(y);
                G[y].push_back(x);
            }
            memset(dfn,0,sizeof dfn);
            memset(low,0,sizeof low);
            memset(isBri,0,sizeof isBri);
            memset(belong,0,sizeof belong);
            dfs_clock=cnt_bri=0;
    //      dfs(1,-1);//tarjan
            dfs(1,0);//tarjan
    //      dfs2(1,0);//lca
    //      printf("%d
    ",cnt_bri);
            int k;
            scanf("%d",&k);
            while(k--){
                int x,y;
                scanf("%d%d",&x,&y);
                if(belong[x]!=belong[y]){
    //              int anc=lca(x,y);
    //              mark(x,anc);
    //              mark(y,anc);
                    func(x,y);
                }
                printf("%d
    ",cnt_bri);
            }
            printf("
    ");
        }
        return 0;
    }
    

    后记

    此题巨坑,由于N的范围太大,导致写lca的时候树上倍增会MLE,所以这里要写暴力的。
    但是我感觉我的暴力lca好像有点错了,不过莫名其妙地也A了。
    有空改一下。
    
  • 相关阅读:
    第一章 线性模型
    Kaggle比赛:从何着手?
    Kaggle初学者五步入门指南,七大诀窍助你享受竞赛
    3.深度学习的实用层面
    软件工程面试题
    PyQT5速成教程-4 Qt Designer实战[上]
    PyQT5速成教程-3 布局管理
    PyQT5速成教程-1 简介与环境搭建
    Anaconda 使用指南
    webpack的loader的原理和实现
  • 原文地址:https://www.cnblogs.com/yohanlong/p/6058148.html
Copyright © 2011-2022 走看看