poj 2553 The Bottom of a Graph

求解的是有向图中满足“自己可达的顶点都能到达自己”的顶点个数
如果强连通分量中某个顶点,还能到达分量外的顶点,则该连通分量不满足要求
// 因此,本题要求的是将强连通分量缩点后所构造的新图中出度为0的顶点个数

// 如果某个新图的节点出度数为0 且是缩点而来 那么该强连通分量里面的点都是符合要求的
#include <iostream> #include <algorithm> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <string.h> using namespace std; #define MOD 1000000007 #define maxn 60100 #define maxm 10010 struct Edge{ int to; int next; Edge(){}; Edge(int u,int v){to=u;next=v;} }E[maxn]; stack<int> S; int V[maxm],num; int belong[maxm]; int pre[maxm]; int dfst,scc; int ans; bool tag[maxm]; int out[maxm]; void init(int n){ dfst=scc=0; num=0; ans=0; while(!S.empty()) S.pop(); for(int i=1;i<=n;i++){ V[i]=-1; pre[i]=0; belong[i]=0; } } void add(int u,int v){ E[num].to=v; E[num].next=V[u]; V[u]=num++; } int tarjan(int u){ int lowu=pre[u]=++dfst; int v,e; S.push(u); for(e=V[u];e!=-1;e=E[e].next){ v=E[e].to; if(!pre[v]){ int lowv=tarjan(v); lowu=min(lowu,lowv); } else if(!belong[v]) lowu=min(lowu,pre[v]); } if(lowu==pre[u]){ scc++; for(;;){ int x=S.top();S.pop(); belong[x]=scc; if(x==u) break; } } return lowu; } int main() { int n,m,T; int u,v; int i,j=1; //scanf("%d",&T); while(scanf("%d",&n),n){ scanf("%d",&m); init(n); for(i=1;i<=m;i++){ scanf("%d %d",&u,&v); add(u,v); } for(i=1;i<=n;i++) if(!pre[i]) tarjan(i); // for(i=1;i<=n;i++) printf("%d ",belong[i]); for(i=1;i<=scc;i++) out[i]=0,tag[i]=0; int e,u,v; for(i=1;i<=n;i++) { for(e=V[i];e!=-1;e=E[e].next){ u=belong[i]; v=belong[E[e].to]; if(u!=v) out[u]++;//,printf("v=%d ",v); } } int flag=0,rc; for(i=1;i<=scc;i++) if(!out[i]) tag[i]=1,flag=1; if(!flag){printf("\n\n");continue;} flag=0; for(i=1;i<=n;i++) if(tag[belong[i]]) { if(flag)printf(" %d",i); else {flag=1;printf("%d",i);} } printf("\n"); } return 0; }

 

你可能感兴趣的:(Graph)