poj 3177 Redundant Paths tarjan

在一个无向图中要增加几条边才能使得整个图成为双连通,对tarjan算法进行更改,求得去掉割边都的叶子节点的个数,这个数目要是为1,ans=0.否则,ans=(n+1)/2.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=5e3+9;
struct
{
    int to,next;
}e[maxn<<2];
int head[maxn],lon;
void edgeini()
{
    memset(head,-1,sizeof(head));
    lon=-1;
}
void edgemake(int from,int to)
{
    e[++lon].to=to;
    e[lon].next=head[from];
    head[from]=lon;
}
int dfn[maxn],low[maxn],instack[maxn],count,stack[maxn],top;
int ans;
void tarjan(int t,int flag,int from)
{
    int kk=0;
    dfn[t]=low[t]=++count;
    instack[t]=1;
    stack[++top]=t;
    for(int k=head[t];k!=-1;k=e[k].next)
    {
        if(k==(flag^1)) continue;
        int u=e[k].to;
        if(dfn[u]==-1)
        {
            ++kk;
            tarjan(u,k,t);
            low[t]=min(low[t],low[u]);
        }
        else if(instack[u])
        {
            low[t]=min(low[t],dfn[u]);
        }
    }
    if(low[t]==dfn[t])
    {
        int cnt=top;
        while(stack[top]!=t)
        {
            instack[stack[top--]]=0;
        }
        instack[stack[top--]]=0;
        if(cnt-top+low[t]-1==count)
        {
            ans++;
        }
        else if(t==from&&kk==1)
        ans++;
    }
}

int main()
{
   // freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
    edgeini();
    for(int i=1,from,to;i<=m;i++)
    {
        scanf("%d %d",&from,&to);
        edgemake(from,to);
        edgemake(to,from);
    }
    memset(dfn,-1,sizeof(dfn));
    memset(instack,0,sizeof(instack));
    count=top=ans=0;
    tarjan(1,-1,1);
    if(ans==1)
    printf("0\n");
    else
    printf("%d\n",(ans+1)/2);
}
    return 0;
}

你可能感兴趣的:(poj 3177 Redundant Paths tarjan)