您的位置:首页 > 其它

[Tarjan]BZOJ 1051—— [HAOI2006]受欢迎的牛

2017-10-06 11:21 417 查看

[Tarjan]BZOJ 1051—— [HAOI2006]受欢迎的牛

题目梗概

给出A喜欢B的关系,这个关系可以传递。

求被所有牛喜欢的牛的数量。

解题思路

缩点之后,出度为0的强连通分量的大小就是答案。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxm=50005,maxn=10005;
int lnk[maxn],son[maxm],nxt[maxm],stack[maxn],dnf[maxn],low[maxn],id[maxn],ans,tot,t,top,h,f[maxn];
inline int _read(){
int num=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar();
return num;
}
bool vis[maxn],b[maxn][maxn];
void add(int x,int y){
nxt[++tot]=lnk[x];lnk[x]=tot;son[tot]=y;
}
void tarjan(int x){
dnf[x]=low[x]=++t;
vis[x]=1;stack[++top]=x;
for (int j=lnk[x];j;j=nxt[j])
if (dnf[son[j]]==0){tarjan(son[j]);low[x]=min(low[x],low[son[j]]);}
else if (vis[son[j]]) low[x]=min(low[x],dnf[son[j]]);
if (dnf[x]==low[x]){
vis[x]=0;id[x]=++h;
while (stack[top]!=x){
id[stack[top]]=h;
vis[stack[top--]]=0;
}
top--;
}
}
int main(){
freopen("exam.in","r",stdin);
freopen("exam.out","w",stdout);
int n=_read(),m=_read();
for (int i=1;i<=m;i++){
int x=_read(),y=_read();
add(x,y);
}
for (int i=1;i<=n;i++) if (dnf[i]==0) tarjan(i);
for (int i=1;i<=n;i++)
for (int j=lnk[i];j;j=nxt[j])
if (id[i]!=id[son[j]]) f[id[i]]=1;
for (int i=1;i<=n;i++)
if (!f[id[i]]) ans++;
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: