1051: [HAOI2006]受欢迎的牛 (tarjan强连通分量+缩点)
题目大意:CodeVs2822的简单版本
$Tarjan$强连通分量+缩点,若连通块的个数等于一则输出n;若缩点后图中出度为0的点个数为1,输出对应连通块内的点数;否则输出0;
代码中注释部分是调了半个小时没发现有错的地方。。。
1 #include<cstring> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cctype> 6 #define foru(i,x,y) for(int i=x;i<=y;i++) 7 #define ford(i,x,y) for(int i=x;i>=y;i--) 8 #define re(x) x=read() 9 using namespace std; 10 typedef long long LL; 11 typedef double db; 12 const int inf=1e9; 13 const int N=1e6+10; 14 15 struct edge{int to,nxt;}e[N*2]; 16 int dfn[N],low[N],stk[N],head[N],vis[N],bl[N],out[N],x,cnt,cl,ed,ne,n,m,ans; 17 18 void add(int a,int b){ 19 e[++ne]=(edge){b,head[a]};head[a]=ne; 20 } 21 22 int read(){ 23 static int f,x;static char ch; 24 x=f=0;ch=getchar(); 25 while(!isdigit(ch)){f=(ch=='-');ch=getchar();} 26 while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} 27 return f?-x:x; 28 } 29 30 void tarjan(int k){ 31 dfn[k]=low[k]=++cnt;stk[++ed]=k;vis[k]=1; 32 for(int i=head[k];i;i=e[i].nxt){ 33 int v=e[i].to; 34 if(!dfn[v]){ 35 tarjan(v); 36 low[k]=min(low[k],low[v]); 37 } 38 else if(vis[v])low[k]=min(low[k],dfn[v]); 39 } 40 int p; 41 if(low[k]==dfn[k]){ 42 cl++;//x++; 43 do{ 44 p=stk[ed--]; 45 bl[p]=cl; 46 vis[p]=0; 47 }while(p!=k); 48 } 49 } 50 51 int main(){ 52 int u,v; 53 re(n);re(m); 54 foru(i,1,m){ 55 re(u);re(v); 56 add(u,v); 57 } 58 foru(i,1,n)if(!dfn[i])tarjan(i); 59 if(cl==1){printf("%d\n",n);return 0;} 60 foru(k,1,n) 61 for(int i=head[k];i;i=e[i].nxt) 62 if(bl[k]!=bl[e[i].to])out[bl[k]]++; 63 v=0; 64 foru(i,1,cl)if(!out[i]){v++;u=i;} 65 if(v==1){ 66 foru(i,1,n)if(bl[i]==u)ans++; 67 printf("%d\n",ans);return 0; 68 } 69 else puts("0"); 70 71 // if(v==1) 72 // foru(i,1,n)if(bl[i]==u)ans++; 73 // else ans=0; 74 // printf("%d\n",ans); 75 return 0; 76 }