[POJ1144]Network(tarjan求割点)

来源:互联网 发布:smartpss监控软件 编辑:程序博客网 时间:2024/06/05 07:29

题目描述

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

题解

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

代码

#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define N 20005int 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);    }}
0 0