如果对tarjan算法有所遗忘,请参见千古的博客
题目背景
POJ2186
HAOI2006 DAY1 T3
题目描述
每一头牛的愿望就是变成一头最受欢迎的牛。现在有 N 头牛,给你 M 对整数(A,B),表示牛A认为牛B受欢迎。这种关系是具有传递性的,如果 A 认为 B 受欢迎,B 认为 C 受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
输入格式
第一行两个数 N,M 。
接下来 M 行,每行两个数 A,B,意思是 A 认为 B 是受欢迎的(给出的信息有可能重复,即有可能出现多个 A,B)
输出格式
输出一个整数,即有多少头牛被所有的牛认为是受欢迎的。如果没有满足这种条件的情况,输出“0”。
样例数据
输入
3 3
1 2
2 1
2 3
输出
1
备注
【样例说明】
只有牛 3 是受到所有牛欢迎的。
【数据范围】
10% 的数据:N≤20;M≤50
30% 的数据:N≤1000;M≤20000
70% 的数据:N≤5000;M≤50000
100% 的数据:N≤10000;M≤50000
分析: Tarjan模板
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;
int getint()
{
int sum=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-1;
ch=getchar();
}
for(;isdigit(ch);ch=getchar())
sum=(sum<<3)+(sum<<1)+ch-48;
return sum*f;
}
const int maxn=10010;
const int maxm=50010;
int tot=1,n,m,x,y,sum,bh,dep,top,cnt,ans;//tot=1要养成习惯,因为在有向图tarjan中可能会用到异或求对边的情况
int first[maxn],nxt[maxm],to[maxm];
int zhan[maxn],dfn[maxn],low[maxn],qlt[maxn];
bool bj[maxn],ruzhan[maxn];
void addedge(int x,int y)
{
tot++;
nxt[tot]=first[x];
first[x]=tot;
to[tot]=y;
}
void tarjan(int u)
{
dfn[u]=++dep;//不要用index,linux环境下会死的
low[u]=dep;
ruzhan[u]=true;
zhan[top]=u;
top++;
for(int p=first[u];p;p=nxt[p])
{
int v=to[p];
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else
{
if(ruzhan[v])//只有栈内横叉边才能更新
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
cnt++;
while(zhan[top]!=u)
{
top--;
qlt[zhan[top]]=cnt;
ruzhan[zhan[top]]=false;
}
}
}
int main()
{
freopen("cows.in","r",stdin);
freopen("cows.out","w",stdout);
n=getint(),m=getint();
for(int i=1;i<=m;++i)
{
x=getint(),y=getint();
addedge(x,y);
}
for(int i=1;i<=n;++i)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;++i)
for(int p=first[i];p;p=nxt[p])
{
int v=to[p];
if(qlt[v]!=qlt[i])
bj[qlt[i]]=1;//这个连通块有出度
}
for(int i=1;i<=cnt;++i)
if(bj[i]==0)
{
sum++;
bh=i;
}
if(sum==1)//只能有一个出度为0的连通块,不然就成了有两批牛互相不认为对方受欢迎,也就没有一只满足受所有牛欢迎了
{
for(int i=1;i<=n;++i)
if(qlt[i]==bh)
ans++;
cout<<ans<<'\n';
}
else
cout<<0<<'\n';
return 0;
}
本题结。