zoukankan      html  css  js  c++  java
  • 【POJ 3177】Redundant Paths(边双连通分量)

    求出每个边双连通分量缩点后的度,度为1的点即叶子节点。原图加上(leaf+1)/2条边即可变成双连通图。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <map>
    
    using namespace std;
    const int N = 5010;
    const int M = 10010;
    struct Edge
    {
        int to,next;
        bool cut;
    }edge[M];
    int head[N],tot;
    int Low[N],DFN[N],Stack[N],Belong[N];
    int Index,top;
    int block;
    bool Instack[N];
    int bridge;
    void addedge(int u,int v)
    {
        edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
        edge[tot].cut=false;
    }
    void Tarjan(int u,int pre)
    {
        int v;
        Low[u] = DFN[u] = ++Index;
        Stack[top++] = u;
        Instack[u] = true;
        for(int i = head[u];~i;i = edge[i].next)
        {
            v = edge[i].to;
            if(v == pre)continue;
            if( !DFN[v] )
            {
                Tarjan(v,u);
                if( Low[u] > Low[v] )Low[u] = Low[v];
                if(Low[v] > DFN[u])//
                {
                    bridge++;
                    edge[i].cut = true;
                    edge[i^1].cut = true;
                }
            }
            else if(Instack[v] && Low[u] > DFN[v])
                Low[u] = DFN[v];
        }
        if(Low[u] == DFN[u])
        {
                    block++;
                    do
                    {
                            v = Stack[--top];
                            Instack[v] = false;
                            Belong[v] = block;
                    }
                    while( v != u);
        }
    }
    int du[N];//缩点后形成树,每个点的度数
    void solve(int n)
    {
            memset(DFN,0,sizeof(DFN));
            memset(Instack,false,sizeof Instack);
            Index = block = top = 0;
            Tarjan(1,0);
            int ans = 0;
            memset(du,0,sizeof(du));
            for(int i = 1;i <= n;i++)
                for(int j = head[i];~j;j = edge[j].next)
                    if(edge[j].cut)
                        du[Belong[i]]++;
            for(int i = 1;i <= block;i++)
                if(du[i]==1)
                    ans++;
            printf("%d
    ",(ans+1)/2);
    }
    void init()
    {
            tot = 0;
            memset(head,-1,sizeof head);
    }
    int main()
    {
        int n,m;
        int u,v;
        while(scanf("%d%d",&n,&m)==2)
        {
            init();
            while(m--)
            {
                scanf("%d%d",&u,&v);
                addedge(u,v);
                addedge(v,u);
            }
            solve(n);
        }
        return 0;
    }

      

  • 相关阅读:
    常用Linux命令
    SQL必知必会-笔记
    【ubuntu】install openbox+tint2+bmenu on ubuntu12.04.4
    【ruby】安装Ruby
    【ruby】快速安装gems的方法
    【sinatra】设置默认的端口
    【sinatra】修改默认ip绑定
    【sinatra】结合Padrino framework
    【sinatra】安装测试
    【rails3教材】博客构建过程2
  • 原文地址:https://www.cnblogs.com/flipped/p/5759360.html
Copyright © 2011-2022 走看看