[BZOJ1051][HAOI2006]受欢迎的牛(tarjan)

题目描述

传送门

题解

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

代码

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

int 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
#include
#include
#include
#include
using namespace std;
#define N 50005

int 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");
}

你可能感兴趣的:(题解,省选,tarjan)