您的位置:首页 > 其它

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

2016-11-01 16:22 399 查看

题目描述

传送门

题解

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

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 50005

int n,m,dfs_clock,scc,ans,ansk;
int x
,y
;
int tot,point
,nxt
,v
;
int dfn
,low
,st
,t,out
,belong
,cnt
;bool vis
;

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 50005

int n,m,dfs_clock,scc,ans,ansk;
int x
,y
;
int tot,point
,nxt
,v
;
int dfn
,low
,st
,t,out
,belong
,cnt
;bool vis
;
int father
,stack
,cur
;

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");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: