POJ 2553 The Bottom of a Graph(强连通分量)

 

题目大意

 

给你一个含有 n(1<=n<=5000) 个节点的有向图,判断图中哪些点事 sink

sink 的定义:如果 u 是 sink,所有 u 能够到的点 v,v 也能到 u

 

做法分析

 

先缩点,形成的 DAG 中,那些出度为 0 的点就是答案

证明如下(反证法):

        令 u 是 DAG 中的一个 sink

        假设 u 的出度不为 0,即在 DAG 中存在一个点 v,使得 u 能够到达 v。

        根据 sink 的定义:所有 u 能够到达的节点也能到达 u,那么 v 也能到达 u

        与 DAG 这一大前提矛盾

        故假设不成立,即 u 的出度为 0

所以找出那些出度为 0 的强连通分量就是我们最终的答案

 

参考代码

 

POJ 2553
 1 #include <vector>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <stack>
 6 #include <iostream>
 7 
 8 using namespace std;
 9 
10 const int N=5006;
11 
12 vector <int> arc[N], scc[N], ans;
13 int n, m, ind, T;
14 int dfn[N], low[N], id[N];
15 bool vs[N];
16 stack <int> s;
17 
18 void tarjan(int u)
19 {
20     s.push(u), vs[u]=1;
21     dfn[u]=low[u]=T++;
22     int len=(int)arc[u].size();
23     for(int i=0; i<len; i++)
24     {
25         int v=arc[u][i];
26         if(dfn[v]==-1)
27         {
28             tarjan(v);
29             if(low[v]<low[u]) low[u]=low[v];
30         }
31         else if(vs[v] && low[u]>dfn[v]) low[u]=dfn[v];
32     }
33     if(low[u]==dfn[u])
34     {
35         for(int v; 1; )
36         {
37             v=s.top();
38             s.pop(), vs[v]=0;
39             id[v]=ind, scc[ind].push_back(v);
40             if(v==u) break;
41         }
42         ind++;
43     }
44 }
45 
46 int main()
47 {
48     while(scanf("%d", &n), n!=0)
49     {
50         scanf("%d", &m);
51         for(int i=1; i<=n; i++) arc[i].clear();
52         for(int i=0, a, b; i<m; i++)
53         {
54             scanf("%d%d", &a, &b);
55             arc[a].push_back(b);
56         }
57         for(int i=0; i<=n; i++) dfn[i]=-1, vs[i]=0, scc[i].clear();
58         while(!s.empty()) s.pop();
59         ind=T=0;
60         for(int i=1; i<=n; i++) if(dfn[i]==-1) tarjan(i);
61         for(int i=0; i<ind; i++) dfn[i]=0;
62         for(int i=1; i<=n; i++)
63         {
64             int len=(int)arc[i].size(), u=id[i];
65             for(int j=0; j<len; j++)
66             {
67                 int v=id[arc[i][j]];
68                 if(v!=u) dfn[u]++;
69             }
70         }
71         ans.clear();
72         for(int i=0; i<ind; i++)
73         {
74             if(dfn[i]!=0) continue;
75             int len=(int)scc[i].size();
76             for(int j=0; j<len; j++) ans.push_back(scc[i][j]);
77         }
78         sort(ans.begin(), ans.end());
79         int len=(int)ans.size();
80         for(int i=0; i<len; i++)
81         {
82             printf("%d", ans[i]);
83             if(i!=len-1) printf(" ");
84         }
85         printf("\n");
86     }
87     return 0;
88 }

AC通道

POJ 2553 The Bottom of a Graph

原文地址:https://www.cnblogs.com/zhj5chengfeng/p/2964010.html