强连通分量 Kosaraju算法
伪代码(摘自Introduction to Algorithm 3rd Edition):
Strongly_connected_components( G )
1. call DFS(G) to compute finishing time u.f for each vertex u
2. compute GT
3. call DFS(GT), but in the main loop of DFS, consider the vertices in order of decreasing u.f
4. output the vertices of each tree in the dfs forest formed in line 3 as a scc
分析:对于图G中的节点a, dfs( a )可求出所有a可达的节点,对于把所有边反向的GT,dfs( a )可求出所有可达a的节点。
集合{a可达}与集合{可达a}的交集就是a属于的scc。
证明:对两个几个交集中任意两点b,c,b与a互相可达,c与a互相可达,所以b与c互相可达。
为了避免集合求交集的操作,如果在执行第3步的时候,所有点都是{a可达},就可以了。
这就是第1步的目的,求出dfs(G)每个节点的完成时间,对于任意节点b,b.f > a.f, 那么b肯定不属于{a可达},因为如果a可达b,那么b一定在a的深搜树中。
POJ 2186 Popular Cows
题目大意:牧场有N头牛,牛可以认为另一头牛popular,求被其他所有牛认为popular的数目。
思路:对于一个强连通分量中的牛,如果一头牛是解,那这个分量中的所有牛都是解。先求强连通分量,把每个分量变成一个节点,原图就压缩成一个DAG。 在DAG中如果有两个或以上的scc的出度为0,那么无解,否则那个出度为0的scc就是解。