bzoj1051: [HAOI2006]受欢迎的牛
tarjan缩点。判断是否只有一个没有出边。是则输出该点点数
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<stack> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define REP(i,s,t) for(int i=s;i<=t;i++) #define op() clr(head,0);pt=edges; #define qwq(x) for(edge *o=head[x];o;o=o->next) int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)){ if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=10005; const int maxn=50005; const int inf=0x7f7f7f7f; struct edge{ int to;edge *next; }; edge edges[maxn],*pt,*head[nmax]; int pre[nmax],sccno[nmax],out[nmax],scc_cnt,dfs_clock; stack<int>s; void adde(int u,int v){ pt->to=v;pt->next=head[u];head[u]=pt++; } int dfs(int x){ int lowu=pre[x]=++dfs_clock;s.push(x); qwq(x) { int to=o->to; if(!pre[to]) lowu=min(lowu,dfs(to)); else if(!sccno[to]) lowu=min(lowu,pre[to]); } if(lowu==pre[x]){ scc_cnt++; while(1){ int X=s.top();s.pop(); sccno[X]=scc_cnt; if(x==X) break; } } return lowu; } void init(){ op();clr(out,false);clr(pre,0);clr(sccno,0);dfs_clock=scc_cnt=0; } int main(){ init(); int n=read(),m=read(),u,v,ans=0,cur,cnt=0; rep(i,m) u=read(),v=read(),adde(u,v); rep(i,n) if(!pre[i]) dfs(i); rep(i,n) qwq(i) if(sccno[i]!=sccno[o->to]) out[sccno[i]]=true; rep(i,scc_cnt) if(!out[i]) cnt++,cur=i; if(cnt==1) rep(i,n) if(sccno[i]==cur) ans++; printf("%d\n",ans); }
1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4144 Solved: 2219
[Submit][Status][Discuss]
Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
1 2
2 1
2 3
Sample Output
1
HINT
100%的数据N<=10000,M<=50000