1. 程式人生 > >【bzoj1051】【HAOI2006】受歡迎的牛

【bzoj1051】【HAOI2006】受歡迎的牛

getch getchar while fir getc cout emp con 關系

題目描述

每頭奶牛都夢想成為牛棚裏的明星。被所有奶牛喜歡的奶牛就是一頭明星奶牛。所有奶牛都是自戀狂,每頭奶牛總是喜歡自己的。奶牛之間的“喜歡”是可以傳遞的——如果A喜歡B,B喜歡C,那麽A也喜歡C。牛欄裏共有N 頭奶牛,給定一些奶牛之間的愛慕關系,請你算出有多少頭奶牛可以當明星。


輸入

第一行:兩個用空格分開的整數:N和M

第二行到第M + 1行:每行兩個用空格分開的整數:A和B,表示A喜歡B


輸出

第一行:單獨一個整數,表示明星奶牛的數量


樣例輸入

3 3
1 2
2 1
2 3


樣例輸出

1



題解

tarjan縮點模版。

#include<cmath>
#include
<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=10000+50; const int maxm=50000+50; int fir[maxn],to[maxm],nex[maxm],ecnt,deep,sum; int n,m,x,y,col[maxn],du[maxn],cnt[maxn],stack[maxn],low[maxn],dfn[maxn],t,tmp;
bool vis[maxn]; void add_edge(int u,int v){ nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v; } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<0||cc>9)&&cc!=-) cc=getchar(); if(cc==-) ff=-1,cc=getchar(); while(cc>=
0&&cc<=9) aa=aa*10+cc-0,cc=getchar(); aa*=ff; } int tarjan(int u){ dfn[u]=++deep; low[u]=deep; vis[u]=1; stack[++t]=u; for(int e=fir[u];e;e=nex[e]){ int v=to[e]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else{ if(vis[v]) low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]){ col[u]=++sum; vis[u]=0; while(stack[t]!=u){ col[stack[t]]=sum; vis[stack[t--]]=0; } t--; } } int main(){ read(n),read(m); for(int i=1;i<=m;i++){ read(x),read(y); add_edge(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++){ for(int e=fir[i];e;e=nex[e]){ int v=to[e]; if(col[i]!=col[v]) du[col[i]]++; } cnt[col[i]]++; } for(int i=1;i<=sum;i++) if(du[i]==0){ tmp++;x=i; } if(tmp==0) cout<<0<<endl; else if(tmp>1) cout<<0<<endl; else cout<<cnt[x]<<endl; return 0; }

【bzoj1051】【HAOI2006】受歡迎的牛