题目大意:给出一个有向图,求有多少个结点能被任意一个结点到达
如果图有环,由于同一个强连通分量中的结点相互可达(互相喜欢),它们可以看作一个点(权值为强连通分量的大小)
因此,此题的解法为寻找强连通分量并缩点,之后按无环图处理即可
一个多月没看,全都忘干净。。。
#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;
}