[BZOJ1051][HAOI2006]受欢迎的牛(Tarjan求强连通分量)

来源:互联网 发布:北京java培训 编辑:程序博客网 时间:2024/05/18 09:10

题目描述

传送门

题解

求出度为0的连通分量的个数,如果个数为1就输出这个强连通分量中点的个数,否则输出0。

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 50005int n,m,dfs_clock,scc,ans,ansk;int x[N],y[N];int tot,point[N],nxt[N],v[N];int dfn[N],low[N],st[N],t,out[N],belong[N],cnt[N];bool vis[N];void add(int x,int y){    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void tarjan(int x){    dfn[x]=low[x]=++dfs_clock;vis[x]=1;st[++t]=x;    for (int i=point[x];i;i=nxt[i])        if (!dfn[v[i]])        {            tarjan(v[i]);            low[x]=min(low[x],low[v[i]]);        }        else if (vis[v[i]])            low[x]=min(low[x],dfn[v[i]]);    if (dfn[x]==low[x])    {        int now=0;++scc;        while (now!=x)        {            now=st[t--];            belong[now]=scc;            ++cnt[scc];            vis[now]=0;        }    }}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=m;++i)    {        scanf("%d%d",&x[i],&y[i]);        add(x[i],y[i]);    }    for (int i=1;i<=n;++i)        if (!dfn[i]) tarjan(i);    for (int i=1;i<=m;++i)        if (belong[x[i]]!=belong[y[i]])            ++out[belong[x[i]]];    for (int i=1;i<=scc;++i)        if (!out[i]) ++ans,ansk=i;    if (ans==1) printf("%d\n",cnt[ansk]);    else puts("0");}

手工栈

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 50005int n,m,dfs_clock,scc,ans,ansk;int x[N],y[N];int tot,point[N],nxt[N],v[N];int dfn[N],low[N],st[N],t,out[N],belong[N],cnt[N];bool vis[N];int father[N],stack[N],cur[N];void add(int x,int y){    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void tarjan(int x){    int tmp=0;t=0;stack[++tmp]=x;    dfn[x]=low[x]=++dfs_clock;vis[x]=1;st[++t]=x;cur[x]=point[x];    while (tmp)    {        int x=stack[tmp];        if (!cur[x])        {            --tmp;            if (dfn[x]==low[x])            {                int now=0;++scc;                while (now!=x)                {                    now=st[t--];                    belong[now]=scc;                    ++cnt[scc];                    vis[now]=0;                }            }            if (father[x]) low[father[x]]=min(low[father[x]],low[x]);            continue;        }        int vt=v[cur[x]];        if (!dfn[vt])        {            stack[++tmp]=vt;st[++t]=vt;            dfn[vt]=low[vt]=++dfs_clock;            father[vt]=x;vis[vt]=1;            cur[vt]=point[vt];        }        else if (vis[vt]) low[x]=min(low[x],dfn[vt]);        cur[x]=nxt[cur[x]];    }}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=m;++i)    {        scanf("%d%d",&x[i],&y[i]);        add(x[i],y[i]);    }    for (int i=1;i<=n;++i)        if (!dfn[i]) tarjan(i);    for (int i=1;i<=m;++i)        if (belong[x[i]]!=belong[y[i]])            ++out[belong[x[i]]];    for (int i=1;i<=scc;++i)        if (!out[i]) ++ans,ansk=i;    if (ans==1) printf("%d\n",cnt[ansk]);    else puts("0");}
0 0