bzoj1051: [HAOI2006]受欢迎的牛(强联通)
1051: [HAOI2006]受欢迎的牛
题目:传送门
题解:
今天又做一道水题...
强联通啊很明显
水个模板之后统计一下每个强联通分量中点的个数,再统计一下出度...
不难发现:缩点之后当且仅当仅有一个强联通分量的出度为0,那么这个强连通分量才可以被所有的点访问..
具体的就自己画下图YY吧...
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define qread(x) x=read() 7 using namespace std; 8 inline int read() 9 { 10 int f=1,x=0;char ch; 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return f*x; 14 } 15 struct node 16 { 17 int x,y,next; 18 }a[51000];int len,last[11000]; 19 void ins(int x,int y) 20 { 21 len++; 22 a[len].x=x;a[len].y=y; 23 a[len].next=last[x];last[x]=len; 24 } 25 int n,m,id,tp,cnt; 26 int belong[11000],dfn[11000],low[11000],sta[11000]; 27 bool v[11000]; 28 void dfs(int x) 29 { 30 low[x]=dfn[x]=++id; 31 sta[++tp]=x;v[x]=true; 32 for(int k=last[x];k;k=a[k].next) 33 { 34 int y=a[k].y; 35 if(dfn[y]==-1) 36 { 37 dfs(y); 38 low[x]=min(low[x],low[y]); 39 } 40 else 41 { 42 if(v[y]==true) 43 low[x]=min(low[x],dfn[y]); 44 } 45 } 46 if(low[x]==dfn[x]) 47 { 48 int i;cnt++; 49 do{ 50 i=sta[tp--]; 51 v[i]=false; 52 belong[i]=cnt; 53 }while(i!=x); 54 } 55 } 56 int num[11000],chu[11000]; 57 int main() 58 { 59 qread(n);qread(m); 60 for(int i=1;i<=m;i++) 61 { 62 int x,y; 63 qread(x);qread(y); 64 ins(x,y); 65 } 66 id=tp=cnt=0; 67 memset(dfn,-1,sizeof(dfn)); 68 memset(low,0,sizeof(low)); 69 memset(belong,0,sizeof(belong)); 70 memset(v,false,sizeof(v)); 71 for(int i=1;i<=n;i++) 72 if(dfn[i]==-1) 73 dfs(i); 74 if(cnt==1){printf("%d\n",n);return 0;} 75 memset(num,0,sizeof(num)); 76 memset(chu,0,sizeof(chu)); 77 for(int i=1;i<=n;i++)num[belong[i]]++; 78 for(int i=1;i<=len;i++) 79 if(belong[a[i].x]!=belong[a[i].y]) 80 chu[belong[a[i].x]]++; 81 int s=0,k; 82 for(int i=1;i<=cnt;i++)if(chu[i]==0){s++;k=i;} 83 if(s==1)printf("%d\n",num[k]); 84 else printf("0\n"); 85 return 0; 86 }
又水一发...