zoukankan      html  css  js  c++  java
  • POJ3694 Network(tarjan求桥)

    给出一个无向连通图,问加入边的过程中,桥的个数。

    先用tarjan算法求出桥的总数,标记每个桥的终点。

    每加入两个顶点,就查询两个顶点的lca,把lca路径上的桥都剪掉~

    链式前向星:

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<cstring>
    using namespace std;
    const int maxn=1e6+10;
    int N,M,x,y;
    int head[maxn];
    int tol;
    struct node {
        int u,v,next;
    }edge[maxn];
    void addedge (int u,int v) {
        edge[tol].u=u;
        edge[tol].v=v;
        edge[tol].next=head[u];
        head[u]=tol++;
    } 
    int low[maxn];
    int dfn[maxn];
    int q;
    int pos[maxn];
    int dep[maxn];
    int father[maxn];
    int bridge[maxn];
    int depth[maxn];
    int cnt;
    int scc;
    int ans;
    stack<int> st;
    void init () {
        fill(low,low+maxn,0);
        fill(dfn,dfn+maxn,0);
        fill(pos,pos+maxn,0);
        fill(depth,depth+maxn,0);
        fill(father,father+maxn,0);
        fill(bridge,bridge+maxn,0);
        memset(head,-1,sizeof(head));
        tol=0;
        cnt=0;
        scc=0;
        ans=0;
    }
    void tarjan (int x,int pre) {
        low[x]=dfn[x]=++cnt;
        depth[x]=depth[pre]+1;
        for (int i=head[x];i!=-1;i=edge[i].next) {
            int v=edge[i].v;
            if (v==pre) continue;
            if (!low[v]) {
                father[v]=x;
                tarjan(v,x);
                low[x]=min(low[x],low[v]);
                if (low[v]>dfn[x]) {
                    ans++;
                    bridge[v]=1;
                }
            }
            else if (!pos[v]) 
               low[x]=min(low[x],dfn[v]);
        }
    }
    void lca (int u,int v) {
        while (depth[u]<depth[v]) {
            if (bridge[v]) {
                bridge[v]=0;
                ans--;
            }
            v=father[v];
        }
        while (depth[u]>depth[v]) {
            if (bridge[u]) {
                bridge[u]=0;
                ans--;
            }
            u=father[u];
        }
        while (u!=v) {
            if (bridge[u]) {
                bridge[u]=0;
                ans--;
            } 
            if (bridge[v]) {
                bridge[v]=0;
                ans--;
            }
            u=father[u];
            v=father[v];
        }
    }
    int main () {
        int t=1;
        while (~scanf("%d%d",&N,&M)) {
            if (N==0&&M==0) break;
            init();
            for (int i=0;i<M;i++) {
                scanf("%d%d",&x,&y);
                addedge(x,y);
                addedge(y,x);
            }
            for (int i=1;i<=N;i++) 
                if (!low[i]) tarjan(i,i);
            scanf("%d",&q);
            printf("Case %d:
    ",t++);
            while (q--) {
                scanf("%d%d",&x,&y);
                lca(x,y);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }

    邻接表:

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<cstring>
    using namespace std;
    const int maxn=1e6+14;
    vector<int> g[maxn];
    int N,M,x,y;
    int low[maxn];
    int dfn[maxn];
    int q;
    int pos[maxn];
    int depth[maxn];
    int father[maxn];
    int bridge[maxn];
    int cnt;
    int scc;
    int ans;
    stack<int> st;
    void init () {
        fill(low,low+maxn,0);
        fill(dfn,dfn+maxn,0);
        fill(pos,pos+maxn,0);
        fill(depth,depth+maxn,0);
        fill(father,father+maxn,0);
        fill(bridge,bridge+maxn,0);
        for (int i=0;i<maxn;i++) g[i].clear();
        while (!st.empty()) st.pop();
        cnt=0;
        scc=0;
        ans=0;
    }
    void tarjan (int x,int pre) {
        low[x]=dfn[x]=++cnt;
        depth[x]=depth[pre]+1;
        for (int i=0;i<g[x].size();i++) {
            if (g[x][i]==pre) continue;
            if (!low[g[x][i]]) {
                father[g[x][i]]=x;
                tarjan(g[x][i],x);
                low[x]=min(low[x],low[g[x][i]]);
                if (low[g[x][i]]>dfn[x]) {
                    ans++;
                    bridge[g[x][i]]=1;
                }
            }
            else if (!pos[g[x][i]]) low[x]=min(low[x],dfn[g[x][i]]);
        }
    }
    void lca (int u,int v) {
        while (depth[u]<depth[v]) {
            if (bridge[v]) {
                bridge[v]=0;
                ans--;
            }
            v=father[v];
        }
        while (depth[u]>depth[v]) {
            if (bridge[u]) {
                bridge[u]=0;
                ans--;
            }
            u=father[u];
        }
        while (u!=v) {
            if (bridge[u]) {
                bridge[u]=0;
                ans--;
            }
            if (bridge[v]) {
                bridge[v]=0;
                ans--;
            }
            u=father[u];
            v=father[v];
        }
    }
    int main () {
        int t=1;
        while (~scanf("%d %d",&N,&M)) {
            if (N==0&&M==0) break;
            init ();
            for (int i=0;i<M;i++) {
                scanf ("%d %d",&x,&y);
                g[x].push_back(y);
                g[y].push_back(x);
            }
            for (int i=1;i<=N;i++) 
            if (!low[i]) tarjan(i,i);
            scanf("%d",&q);
            printf ("Case %d:
    ",t++);
            while (q--) {
                scanf ("%d %d",&x,&y);
                lca (x,y);
                printf ("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    终于,我还是对自己的博客下手了
    对字典进行排序
    小米官网的css3导航菜单
    背景色渐变
    处理手机上点击链接出现的蓝色边框
    如何修改HTML5 input placeholder 颜色
    自定义浏览器滚动条样式
    两行文字,固定宽高,超出部分以三点隐藏
    css3控制div上下跳动-效果图
    css3控制div上下跳动
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12313369.html
Copyright © 2011-2022 走看看