[POJ1144]Network(tarjan求割点)

题目描述

传送门
题意:求一个无向图中割点的数量。

题解

tarjan求割点模板题。
dfn表示点x的时间戳,low表示点x通过其后代最早能到达的点,is_cut表示点x的后代最多能有多少个连通块。
假设一个点是割点,如果这个点是第一个被访问点,那么如果它后代能形成一个以上的连通块的话它就是割点。如果这个点不是第一个被访问的点,那么如果它后代能形成一个或以上的连通块的话它就是割点。

代码

#include
#include
#include
using namespace std;
#define N 20005

int n,m,p,dfs_clock,ans;
int tot,point[N],nxt[N*2],v[N*2];
int dfn[N],low[N],is_cut[N];
bool flag;

void clear()
{
    dfs_clock=ans=0;
    tot=0;memset(v,0,sizeof(v));memset(point,0,sizeof(point));memset(nxt,0,sizeof(nxt));
    memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(is_cut,0,sizeof(is_cut));
}
int read()
{
    int x=0; char ch=getchar();
    while (ch<'0'||ch>'9')
    {
        ch=getchar();
        if (ch=='\n') flag=true;
    }
    while (ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
        if (ch=='\n') flag=true;
    }
    return x;
}
void add(int x,int y)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void tarjan(int x)
{
    dfn[x]=low[x]=++dfs_clock;
    for (int i=point[x];i;i=nxt[i])
        if (!dfn[v[i]])
        {
            tarjan(v[i]);
            low[x]=min(low[x],low[v[i]]);
            if (dfn[x]<=low[v[i]]) is_cut[x]++;
        }
        else low[x]=min(low[x],dfn[v[i]]);
}
int main()
{
    while (1)
    {
        n=read();
        if (!n) break;
        clear();
        while (1)
        {
            m=read();
            if (!m) break;flag=false;
            while (!flag)
            {
                p=read();
                add(m,p);
            }
        }
        for (int i=1;i<=n;++i)
            if (!dfn[i]) tarjan(i);
        for (int i=1;i<=n;++i)
            if ((i==1&&is_cut[i]>1)||(i!=1&&is_cut[i])) ans++;
        printf("%d\n",ans);
    }
}

你可能感兴趣的:(题解,图论算法,tarjan)