poj - 2553 (强连通分量)

题目来源: http://acm.pku.edu.cn/JudgeOnline/problem?id=2553

 

强连通分量,很简单的题目,照着模板水过了。

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
1 #include < iostream >
2 #include < algorithm >
3   using namespace std;
4
5   const int M = 10005 ;
6   int cnt, scnt, nn;
7 int stack[M], ord[M], low[M], id[M], ans[M];
8 bool instack[M], map[M];
9 struct Node
10 {
11 int to;
12 Node * next;
13 };
14 Node * g[M];
15
16
17 bool cmp( int a, int b)
18 {
19 return a < b;
20 }
21
22 void Tarjan( int e) // Tarjan的DFS过程,不断更新 low 和 ord
23 {
24 low[e] = ++ cnt;
25 ord[e] = cnt;
26 stack[ ++ stack[ 0 ]] = e;
27 instack[e] = true ;
28 Node * tmp = g[e];
29
30 while (tmp != NULL)
31 {
32 int t = tmp -> to;
33 if ( ! ord[t])
34 {
35 Tarjan(t);
36 if (low[t] < low[e])
37 low[e] = low[t];
38 }
39 else if (instack[t] && ord[t] < low[e])
40 low[e] = ord[t];
41 tmp = tmp -> next;
42 }
43
44 if (low[e] == ord[e]) // 找到强连通分量的根
45 {
46 int t;
47 scnt ++ ;
48 do // 找出强连通分支中的点
49 {
50 t = stack[stack[ 0 ] -- ];
51 id[t] = scnt;
52 instack[t] = false ;
53 } while (t != e);
54 }
55
56 return ;
57 }
58
59 void find_components( int n) // Tarjan主过程,依次找出没有DFS的点
60 {
61 memset(instack, false , sizeof (instack));
62 memset(ord, 0 , sizeof (ord));
63 cnt = scnt = 0 ;
64 stack[ 0 ] = 0 ; // 记录栈里元素的个数
65 for ( int i = 1 ; i <= n; i ++ )
66 {
67 if ( ! ord[i])
68 Tarjan(i);
69 }
70
71 return ;
72 }
73
74 void insert( int u, int v)
75 {
76 Node * tmp = new Node;
77 tmp -> to = v;
78 tmp -> next = g[u];
79 g[u] = tmp;
80 }
81
82 int main()
83 {
84 int n, m;
85 while (scanf( " %d " , & n) != EOF && n)
86 {
87 scanf( " %d " , & m);
88 memset(g, NULL, sizeof (g));
89 for ( int i = 0 ; i < m; i ++ ) // 建图
90 {
91 int u, v ;
92 scanf( " %d%d " , & u, & v);
93 insert(u, v);
94 }
95
96 find_components(n);
97 nn = scnt;
98 memset(map, false , sizeof (map));
99
100 for ( int i = 1 ; i <= n; i ++ )
101 {
102 Node * tmp;
103 tmp = g[i];
104 while (tmp != NULL)
105 {
106 int e = tmp -> to;
107 if (id[e] != id[i] && ! map[id[i]])
108 map[id[i]] = true ;
109 tmp = tmp -> next;
110 }
111 }
112
113 int k = 0 ;
114 for ( int i = 1 ; i <= n; i ++ )
115 {
116 int pos = id[i];
117 if ( ! map[pos])
118 {
119 ans[k ++ ] = i;
120 }
121 }
122
123 if (k > 0 )
124 {
125 sort(ans, ans + k, cmp);
126 printf( " %d " ,ans[ 0 ]);
127 for ( int i = 1 ; i < k; i ++ )
128 printf( " %d " ,ans[i]);
129 printf( " \n " );
130 }
131 else
132 printf( " \n\n " );
133 }
134 return 0 ;
135 }
136
137
138

 

转载于:https://www.cnblogs.com/zhjjla/archive/2010/05/21/1741180.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值