和hdu的3639有点相似,不过最后求的不太一样。。
方法还是一样的,我也是用强连通分量+反向图做的。。
有一周没写强连通了,,有点手生了,以后要多练习练习。。
题目大意:有N头牛 ,如果a 牛喜欢b牛 而 b牛喜欢c牛,那a和b都喜欢c牛。。
像那种爱屋及乌。。也就是喜欢是可以传递的,问最后 被除它自己之外的所有牛 都喜欢的牛 的数量。。
有那么一点拗口。。。
先用强连通缩点,, 之后建立反向图,,从入度为0的开始深搜,,
如果该点符合条件的话 就加上该点的权值(即是该点所包含的牛的数量),之后输出即可。。。
# include<stdio.h> # include<string.h> # define N 10005 # define M 50005 struct node{ int from,to,next; }edge1[M],edge2[M],edge[M]; int head1[N],head2[N],head[N],Belong[N],in[N]; int visit1[N],visit2[N],visit[N],val[N],T[N]; int Bcnt,Tcnt,tol,tol1,tol2,count; void add(int a,int b) { edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++; edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++; } void add1(int a,int b) { edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++; } void dfs1(int x) { int j; visit1[x]=1; for(j=head1[x];j!=-1;j=edge1[j].next) if(visit1[edge1[j].to]==0) dfs1(edge1[j].to); T[Tcnt++]=x; } void dfs2(int x) { int j; Belong[x]=Bcnt; count++; visit2[x]=1; for(j=head2[x];j!=-1;j=edge2[j].next) if(visit2[edge2[j].to]==0) dfs2(edge2[j].to); } void dfs(int x) { int i; visit[x]=1; count++; for(i=head[x];i!=-1;i=edge[i].next) if(visit[edge[i].to]==0) dfs(edge[i].to); } int main() { int i,a,b,index,n,m,x,y; scanf("%d%d",&n,&m); Tcnt=0; Bcnt=0;//表示强连通分量的个数 tol1=0; tol2=0; for(i=0;i<=n;i++) { head1[i]=-1; head2[i]=-1; visit1[i]=0; visit2[i]=0; } for(i=1;i<=m;i++) { scanf("%d%d",&a,&b); add(a,b); } for(i=1;i<=n;i++) if(visit1[i]==0) dfs1(i); for(i=Tcnt-1;i>=0;i--) { if(visit2[T[i]]==0) { count=0; dfs2(T[i]); val[Bcnt]=count; Bcnt++; } } for(i=0;i<Bcnt;i++) { in[i]=0; head[i]=-1; } for(i=0;i<tol1;i++) { x=Belong[edge1[i].from]; y=Belong[edge1[i].to]; if(x!=y) { in[x]++; add1(y,x); } } index=0; for(i=0;i<Bcnt;i++) { if(in[i]==0) { memset(visit,0,sizeof(visit)); count=0; dfs(i); if(count==Bcnt) {index+=val[i];} } } printf("%d\n",index); return 0; }