bzoj1051: [HAOI2006]受欢迎的牛
裸的tarjan缩点,然后判断谁在链的最后面,具体的体现是有且只有一个点(缩点后)的出度(就是指出去的边的数量)为0,这是显然的
这么裸的题就这样吧(果然蒟蒻只会写裸题),感觉这题似乎是usaco的风格,不知道是不是原题
/**************************************************************
Problem: 1051
User: tym983398371
Language: C++
Result: Accepted
Time:76 ms
Memory:2620 kb
****************************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
struct edge{
int to,next;
};
edge e[50005];
int n,m,cime,cnt,g[10005],ans=0,q[10005],top=0,zn[10005],scc=0;
int h[10005],low[10005],belong[10005],num[10005];
bool vis[10005];
edge sd[50005];
int f[10005];
inline void addedge(const int &from,const int &to)
{
cnt++;e[cnt].to=to;e[cnt].next=g[from];g[from]=cnt;
return ;
}
void dfs(int x)
{
int y;
vis[x]=zn[x]=1;
cime++;
h[x]=low[x]=cime;
top++;
q[top]=x;
for (int i=g[x];i;i=e[i].next)
{
if (!vis[e[i].to])
{
dfs(e[i].to);
low[x]=min(low[x],low[e[i].to]);
}
else if (zn[e[i].to]) low[x]=min(low[x],h[e[i].to]);
}
if (low[x]==h[x])
{
scc++;
while (y!=x)
{
y=q[top];
top--;
zn[y]=0;
belong[y]=scc;
num[scc]++;
}
}
return ;
}
void rebuild()
{
cnt=0;
for (int i=1;i<=n;i++)
{
for (int j=g[i];j;j=e[j].next)
{
if (belong[i]!=belong[e[j].to])
{
cnt++;
sd[cnt].to=belong[e[j].to];
sd[cnt].next=f[belong[i]];
f[belong[i]]=cnt;
}
}
}
return ;
}
void tarjan()
{
for (int i=1;i<=n;i++)
if (!vis[i]) dfs(i);
rebuild();
return ;
}
void work()
{
for (int i=1;i<=scc;i++)
if (!f[i])
{
if (ans)
{
ans=0;return ;
}
ans=num[i];
}
return ;
}
int main()
{
cime=cnt=1;
memset(g,0,sizeof(g));
memset(f,0,sizeof(f));
memset(num,0,sizeof(num));
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
int x,y;
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
}
tarjan();
work();
printf("%d\n",ans);
return 0;
}