图算法(4)-强连通分量

一个图的连通分量即是这样的一个顶点集合,其中各个节点直接都可以相互到达连通。而强连通分量则是这样一个集合的极大值,即:添加任何另外节点,这个集合都不再是连通分量。

计算强连通分量,可以先对原图进行一次DFS遍历,计算得到每个节点的finish time。然后计算转置图,并对转置图进行DFS遍历(其中遍历的主循环,按照原图节点的finish time逆序),这样对转置图DFS遍历得到的每一棵深度遍历树的节点即为一个强连通分量。

算法如下:(用cout输出了强连通分量,每个强连通分量一行,DFS函数与前面相同,只是在最开始一行输出了当前节点)

 1 void GraphTranspose(Graph& g, Graph& t)
 2 {
 3     t.nodemap = g.nodemap;
 4     t.nodes.resize(g.nodes.size());
 5     for (size_t i = 0; i < g.nodes.size(); ++i)
 6     {
 7         t.nodes[i].value = g.nodes[i].value;
 8         Edge e = { i };
 9         for (size_t j = 0; j < g.nodes[i].edges.size(); ++j)
10         {
11             t.nodes[g.nodes[i].edges[j].end].edges.push_back(e);
12         }
13     }
14 }
15 
16 void GetOrder(Graph& g, vector<int>& order)
17 {
18     vector<Node*> s;
19     for (size_t i = 0; i < g.nodes.size(); ++i)
20     {
21         s.push_back(&g.nodes[i]);
22     }
23     sort(s.begin(), s.end(), cmp);
24     
25     order.clear();
26     for (size_t i = 0; i < s.size(); ++i)
27     {
28         order.push_back(g.nodemap[s[i]->value]);
29     }
30 }
31 
32 void StronglyConnectedComponents(Graph& g)
33 {
34     DFS(g);
35     cout << endl;
36     vector<int> order;
37     GetOrder(g, order);
38 
39     Graph t;
40     GraphTranspose(g, t);
41 
42     for (size_t i = 0; i < t.nodes.size(); ++i)
43     {
44         t.nodes[i].p = -1;
45         t.nodes[i].color = WHITE;
46     }
47 
48     time = 0;
49     for (size_t i = 0; i < order.size(); ++i)
50     {
51         int u = order[i];
52         if (t.nodes[u].color == WHITE)
53         {
54             cout << "Comp : ";
55             DFS(t, u);
56             cout << endl;
57         }
58     }
59 }

最后运行可以看到结果。至于为什么不把强连通分量保存在数组里呢?因为太麻烦。。。。如果不用cout输出的话,需要DFS完后,根据p信息重建深度遍历树。

(终于明白为什么STL没有图算法了,因为图的各个问题形式不同,所需要添加的辅助信息也不一样,实在是很难用一个统一的结构表达出来。)

 

posted @ 2014-01-07 16:01  Tiancai Ye  阅读(338)  评论(0)    收藏  举报