【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;
}

  

原文地址:https://www.cnblogs.com/flipped/p/5759360.html