C++ P1726 上白澤慧音
阿新 • • 發佈:2019-02-01
學習了強聯通分量(scc),找了個裸題,用tarjan演算法AC了,Dalao勿噴啊! -_-||
# include <iostream> # include <cstring> # include <vector> # include <stack> using namespace std; int n, m, scctot, scc[5010], low[5010], dfn[5010], dfntot, maxn, num; vector<int> map[5010]; stack<int> s; void tarjan(int u) { low[u] = dfn[u] = ++dfntot; // 訪問步數,後面會不斷更新low // low就是u或u的子樹能夠追溯到的最早的棧中節點的次序號 s.push(u); // u結點入棧,後面用來找一個強連通分量 for(int i = 0; i < map[u].size(); i++) { int v = map[u][i]; if(dfn[v] == 0) { // 當v沒有訪問過時,再tarjan(v),更新low tarjan(v); low[u] = min(low[u], low[v]); } else if(scc[v] == 0) low[u] = min(low[u], dfn[v]); //當v不在某個強連通分量時,再更新low } if(low[u] == dfn[u]) { scctot++; // 強連通分量計數(第幾個) int x = -1, tot = 0; // tot,這個scc有幾個節點 while(x != u) { // 頭不等於尾時(中間的結點就是一個強連通分量的節點) if(++tot > maxn) maxn = tot, num = scctot; // 主要儲存哪個scc中的scctot最多(num) x = s.top(); s.pop(); scc[x] = scctot; // 在一個scc中的所有節點都是第scctot個 } } } int main() { int u, v, t; cin >> n >> m; while(m--) { cin >> u >> v >> t; map[u].push_back(v); if(t == 2) map[v].push_back(u); } for(int i = 1; i <= n; i++) if(dfn[i] == 0) tarjan(i); //在沒找過的節點再找下去 cout << maxn << endl; for(int i = 1; i <= n; i++) if(scc[i] == num) cout << i << " "; // 找到num,輸出 return 0; }