---
# System prepended metadata

title: Strongly Connected Component (SCC)

---

# Strongly Connected Component (SCC)

## Reference
1. http://alrightchiu.github.io/SecondRound/graph-li-yong-dfsxun-zhao-strongly-connected-componentscc.html
2. https://web.ntnu.edu.tw/~algo/Component.html

## 找出所有SCC

![](https://i.imgur.com/wYUef8S.png)

1. 第一次DFS得到的finish之由大到小順序 (finish order)
2. 在GT上進行第二次DFS，就可以分出所有的SCC

```
void dfs(int i, vector<vector<int>> &adj, vector<bool> &visit, vector<int> &finish_order){
    visit[i] = 1;
    for(int j=0;j<adj[i].size();++j){
        if(!visit[adj[i][j]]){
            dfs(adj[i][j], adj, visit, finish_order);
        }
    }
    finish_order.push_back(i);
}

void dfs2(int i, vector<vector<int>> &adj, vector<bool> &visit, int group_idx, vector<int> &result_group, vector<int> &group_size){
    result_group[i] = group_idx;
    group_size[group_idx]++;
    visit[i] = 1;
    for(int j=0;j<adj[i].size();++j){
        if(!visit[adj[i][j]]){
            dfs2(adj[i][j], adj, visit, group_idx, result_group, group_size);
        }
    }
}

int get_SCC(vector<vector<int>> &adj, vector<vector<int>>& transpose_adj, vector<int> &result_group, vector<int> &group_size){
    vector<bool> visit(N, 0);
    vector<int> finish_order;
    // dfs(adj) to get finish order
    for(int i=0;i<N;++i){
        if(!visit[i]){
            dfs(i, adj, visit, finish_order);
        }
    }

    vector<bool> visit2(N, 0);
    int idx = 0;
    // dfs(transpose adj) again in reversed finish order
    for(int i=N-1;i>=0;--i){
        if(!visit2[finish_order[i]]){
            dfs2(finish_order[i], transpose_adj, visit2, idx, result_group, group_size);
            idx++;
        }
    }

    return idx;
}
```

## 畫出SCC Graph
收縮所有有向圖的環，最後畫出的圖是一個DAG。

![](https://i.imgur.com/65jiloS.png)

畫法: 檢查原本的adj list(matrix)，若node i和node j有連線但分屬不同的SCC group；假設node i屬group a、node j屬group b，則a、b間建一條SCC edge。

```
void build_SCC_graph(int component_size, vector<vector<int>> &adj, vector<int> &group, vector<vector<int>> &SCC_graph_adj){
    for(int i=0;i<N;++i){
        for(int j=0;j<adj[i].size();++j){
            // build edge between different group
            if(group[i] != group[adj[i][j]]){
                SCC_graph_adj[group[i]].push_back(group[adj[i][j]]);
            }
        }
    }

}
```

## Example Problem and Code

### 題目
一個有環的有向圖，找到一條含最多不重複的node的路徑(最長路徑)。

### 解
必須先用SCC收縮環，再以DFS搜尋收縮後的SCC Graph並存下finish order。最後DP以finish order順序從leaf至root加總路徑上SCC group的所有node。

### code
```
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

int M, N;

void dfs(int i, vector<vector<int>> &adj, vector<bool> &visit, vector<int> &finish_order){
    visit[i] = 1;
    for(int j=0;j<adj[i].size();++j){
        if(!visit[adj[i][j]]){
            dfs(adj[i][j], adj, visit, finish_order);
        }
    }
    finish_order.push_back(i);
}

void dfs2(int i, vector<vector<int>> &adj, vector<bool> &visit, int group_idx, vector<int> &result_group, vector<int> &group_size){
    result_group[i] = group_idx;
    group_size[group_idx]++;
    visit[i] = 1;
    for(int j=0;j<adj[i].size();++j){
        if(!visit[adj[i][j]]){
            dfs2(adj[i][j], adj, visit, group_idx, result_group, group_size);
        }
    }
}

int get_SCC(vector<vector<int>> &adj, vector<vector<int>>& transpose_adj, vector<int> &result_group, vector<int> &group_size){
    vector<bool> visit(N, 0);
    vector<int> finish_order;
    // dfs(adj) to get finish order
    for(int i=0;i<N;++i){
        if(!visit[i]){
            dfs(i, adj, visit, finish_order);
        }
    }

    vector<bool> visit2(N, 0);
    int idx = 0;
    // dfs(transpose adj) again in reversed finish order
    for(int i=N-1;i>=0;--i){
        if(!visit2[finish_order[i]]){
            dfs2(finish_order[i], transpose_adj, visit2, idx, result_group, group_size);
            idx++;
        }
    }

    return idx;
}

void build_SCC_graph(int component_size, vector<vector<int>> &adj, vector<int> &group, vector<vector<int>> &SCC_graph_adj){
    for(int i=0;i<N;++i){
        for(int j=0;j<adj[i].size();++j){
            // build edge between different group
            if(group[i] != group[adj[i][j]]){
                SCC_graph_adj[group[i]].push_back(group[adj[i][j]]);
            }
        }
    }

}

void dfs_SCC(int i, vector<vector<int>> &adj, vector<bool> &visit, vector<int> &finish_order){
    visit[i] = 1;
    for(int j=0;j<adj[i].size();++j){
        if(!visit[adj[i][j]]){
            dfs_SCC(adj[i][j], adj, visit, finish_order);
        }
    }
    finish_order.push_back(i);
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    vector<vector<int>> adj(200001);
    vector<vector<int>> transpose_adj(2000001);

    cin >> N >> M;

    for(int i=0;i<M;++i){
        int x, y;
        cin >> x >> y;
        adj[x].push_back(y);
        transpose_adj[y].push_back(x);
    }

    vector<int> result_group(N, -1);
    vector<int> group_size(N, 0);

    int component_size = get_SCC(adj, transpose_adj, result_group, group_size);
    vector<vector<int>> SCC_graph_adj(component_size);
    build_SCC_graph(component_size, adj, result_group, SCC_graph_adj);

    vector<bool> visit(component_size, 0);
    vector<int> finish_order;
    for(int i=0;i<component_size;i++){
        if(!visit[i]){
            dfs_SCC(i, SCC_graph_adj, visit, finish_order);
        }
    }

    int ans = -1;
    for(int i=0;i<component_size;i++){
        int m = 0;
        for(int j=0;j<SCC_graph_adj[finish_order[i]].size();++j){
             m = max(m, group_size[SCC_graph_adj[finish_order[i]][j]]);
        }
        group_size[finish_order[i]] += m;
        ans = max(ans, group_size[finish_order[i]]);
    }
    cout << ans << endl;



    return 0;
}

```

