题目大意:给出一个有向图,求有多少个结点能被任意一个结点到达
如果图有环,由于同一个强连通分量中的结点相互可达(互相喜欢),它们可以看作一个点(权值为强连通分量的大小)
因此,此题的解法为寻找强连通分量并缩点,之后按无环图处理即可
一个多月没看,全都忘干净。。。
#include<stdio.h> #include<stdlib.h> #include<string.h> int u[100005]={0},v[100005]={0},first[10005]={0},next[100005]={0}; int pre[10005]={0},lowlink[10005]={0},sccno[10005]={0},num[10005]={0};//SCC相关 int s[10005]={0};//栈 int e=0,clo=0,pscc=0,top=0; void tj(int x,int y) { u[++e]=x; v[e]=y; next[e]=first[x]; first[x]=e; } void dfs(int x) { int i; lowlink[x]=pre[x]=++clo; s[++top]=x; for(i=first[x];i!=0;i=next[i]) { if(pre[v[i]]==0) { dfs(v[i]); if(lowlink[x]>lowlink[v[i]]) lowlink[x]=lowlink[v[i]]; } else if(sccno[v[i]]==0&&lowlink[x]>lowlink[v[i]]) lowlink[x]=lowlink[v[i]]; } if(lowlink[x]==pre[x]) { pscc++; while(1) { sccno[s[top--]]=pscc; num[pscc]++; if(s[top+1]==x) break; } } } int main() { int n,m,i,x,y,e2,flag=0,ans; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); tj(x,y); } for(i=1;i<=n;i++) if(pre[i]==0) dfs(i); e2=e;//以下为缩点过程 e=0; memset(first,0,sizeof(first)); memset(next,0,sizeof(next)); for(i=1;i<=e2;i++) if(sccno[u[i]]!=sccno[v[i]]) tj(sccno[u[i]],sccno[v[i]]);//e恒<=i for(i=1;i<=pscc;i++) if(first[i]==0) { flag++; ans=num[i]; } if(flag==1) printf("%d",ans); else printf("0"); return 0; }