1. 程式人生 > >C++ P1726 上白澤慧音

C++ P1726 上白澤慧音

學習了強聯通分量(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;
}