poj 2553 The Bottom of a Graph(强连通、缩点、出入度)
题意:给出一个有向图G,寻找所有的sink点。“sink”的定义为:{v∈V|∀w∈V:(v→w)⇒(w→v)},对于一个点v,所有能到达的所有节点w,都能够回到v,这样的点v称为sink。
分析:由(v→w),(w→v)可知,节点v,w构成强连通,很自然的想到要缩点。缩点之后,DAG上的每一条边,都是单向的(v->w),无回路(w->v)。
错误:对于v可达的点w,不仅是直接连边——从一个强连通子集A到另一个强连通子集B,意味着,子集A中的点都不可能是sink点。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<stack> 4 #include<algorithm> 5 using namespace std; 6 7 const int MAXN=5555; 8 9 struct Edge{ 10 int v,next; 11 Edge(){} 12 Edge(int _v,int _next):v(_v),next(_next){} 13 }edge[MAXN*MAXN]; 14 15 int head[MAXN],tol; 16 int pre[MAXN],low[MAXN],sccno[MAXN],dfs_clock,scc_cnt; 17 int vis[MAXN]; 18 19 stack<int>stk; 20 21 void init(int n) 22 { 23 tol=0; 24 memset(head,-1,sizeof(head)); 25 } 26 27 void add(int u,int v) 28 { 29 edge[tol]=Edge(v,head[u]); 30 head[u]=tol++; 31 } 32 33 void dfs(int u) 34 { 35 int v; 36 pre[u]=low[u]=++dfs_clock; 37 stk.push(u); 38 for(int i=head[u];i!=-1;i=edge[i].next) 39 { 40 v=edge[i].v; 41 if(!pre[v]){ 42 dfs(v); 43 low[u]=min(low[u],low[v]); 44 }else if(!sccno[v]) 45 low[u]=min(low[u],pre[v]); 46 } 47 if(pre[u]==low[u]){ 48 scc_cnt++; 49 do{ 50 v=stk.top(); 51 stk.pop(); 52 sccno[v]=scc_cnt; 53 }while(u!=v); 54 } 55 } 56 57 void find_scc(int n) 58 { 59 dfs_clock=scc_cnt=0; 60 memset(pre,0,sizeof(pre)); 61 memset(low,0,sizeof(low)); 62 memset(sccno,0,sizeof(sccno)); 63 64 for(int i=1;i<=n;i++) 65 if(!pre[i]) 66 dfs(i); 67 } 68 69 void check(int n) 70 { 71 memset(vis,0,sizeof(vis)); 72 for(int i=1;i<=n;i++) 73 { 74 for(int j=head[i];j!=-1;j=edge[j].next) 75 { 76 int v=edge[j].v; 77 if(sccno[i]!=sccno[v]) 78 vis[sccno[i]]=1; 79 } 80 } 81 } 82 83 void print(int n) 84 { 85 int cnt=0; 86 for(int i=1;i<=n;i++) 87 if(!vis[sccno[i]]){ 88 if(cnt==0)printf("%d",i); 89 else printf(" %d",i); 90 cnt++; 91 } 92 printf("\n"); 93 } 94 95 int main() 96 { 97 int n,m; 98 while(~scanf("%d",&n)) 99 { 100 if(!n) 101 return 0; 102 scanf("%d",&m); 103 104 init(n); 105 for(int i=0;i<m;i++) 106 { 107 int u,v; 108 scanf("%d%d",&u,&v); 109 add(u,v); 110 } 111 112 find_scc(n); 113 114 check(n); 115 116 print(n); 117 } 118 return 0; 119 }