题目是问,一个有向图有多少个点v满足∀w∈V:(v→w)⇒(w→v)。
把图的强连通分量缩点,那么答案显然就是所有出度为0的点。
用Tarjan找强连通分量:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define MAXN 5555 6 #define MAXM 5555*5555 7 struct Edge{ 8 int u,v,next; 9 }edge[MAXM]; 10 int NE,head[MAXN]; 11 void addEdge(int u,int v){ 12 edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u]; 13 head[u]=NE++; 14 } 15 16 int bn,belong[MAXN],stack[MAXN],top; 17 bool instack[MAXN]; 18 int dn,dfn[MAXN],low[MAXN]; 19 void dfs(int u){ 20 dfn[u]=low[u]=++dn; 21 stack[++top]=u; instack[u]=1; 22 for(int i=head[u]; i!=-1; i=edge[i].next){ 23 int v=edge[i].v; 24 if(dfn[v]==0){ 25 dfs(v); 26 low[u]=min(low[u],low[v]); 27 }else if(instack[v]){ 28 low[u]=min(low[u],dfn[v]); 29 } 30 } 31 if(dfn[u]==low[u]){ 32 int v; ++bn; 33 do{ 34 v=stack[top--]; 35 instack[v]=0; 36 belong[v]=bn; 37 }while(u!=v); 38 } 39 } 40 41 int deg[MAXN]; 42 int main(){ 43 int n,m,a,b; 44 while(~scanf("%d",&n) && n){ 45 NE=0; 46 memset(head,-1,sizeof(head)); 47 scanf("%d",&m); 48 while(m--){ 49 scanf("%d%d",&a,&b); 50 addEdge(a,b); 51 } 52 top=dn=bn=0; 53 memset(dfn,0,sizeof(dfn)); 54 memset(instack,0,sizeof(instack)); 55 for(int i=1; i<=n; ++i){ 56 if(dfn[i]==0) dfs(i); 57 } 58 memset(deg,0,sizeof(deg)); 59 for(int i=0; i<NE; ++i){ 60 int u=belong[edge[i].u],v=belong[edge[i].v]; 61 if(u==v) continue; 62 ++deg[u]; 63 } 64 bool first=1; 65 for(int i=1; i<=n; ++i){ 66 if(deg[belong[i]]==0){ 67 if(first) first=0; 68 else putchar(' '); 69 printf("%d",i); 70 } 71 } 72 putchar(' '); 73 } 74 return 0; 75 }