POJ - 3180 The Cow Prom ( korasaju 演算法模板)
阿新 • • 發佈:2020-07-29
The Cow Prom POJ - 3180
題意:
奶牛圓舞:N頭牛,M條有向繩子,能組成幾個歌舞團(團內奶牛數 n >= 2)?要求順時針逆時針都能帶動舞團內所有牛。
分析:
所謂能帶動,就是舞團構成一個強連通分量,就是赤裸裸的SCC。
程式碼實現:很好的一道題,有利於理解 korasaju 演算法
#include<iostream> #include<queue> #include<vector> using namespace std; #define ms(a,b) memset(a,b,sizeof a) const int maxn = 1e5 + 10; int V; // 頂點數 vector<int> G[maxn]; // 圖的鄰接表表示 vector<int> rG[maxn]; // 反向圖 vector<int> vs; // 後序遍歷順序的頂點列表 bool book[maxn]; // 訪問標記 int cmp[maxn]; // 所屬強連通分量的拓補序 void add_edge(const int& from, const int& to) { G[from].push_back(to); rG[to].push_back(from); } void dfs(const int& v) { book[v] = true; for (int i = 0; i < G[v].size(); ++i) if (!book[G[v][i]])dfs(G[v][i]); vs.push_back(v); } void rdfs(const int& v, const int& k) { book[v] = true; cmp[v] = k; for (int i = 0; i < rG[v].size(); ++i) if (!book[rG[v][i]])rdfs(rG[v][i], k); } int scc() { ms(book, false); vs.clear(); for (int v = 0; v < V; ++v) if (!book[v])dfs(v); ms(book, false); int k = 0; for (int i = vs.size() - 1; i >= 0; --i) if (!book[vs[i]])rdfs(vs[i], k++); //cout << k << endl; //3個連通分量 return k; } int main() { //freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int m; cin >> V >> m; for (int i = 0; i < m; ++i) { int from, to; cin >> from >> to; add_edge(--from, --to); } int n = scc(); vector<int>count(n, 0); for (int v = 0; v < V; ++v) { //cout << cmp[v] << " "; // 2 2 1 2 0 ++count[cmp[v]]; } //cout << endl; int ans = 0; for (int i = 0; i < n; ++i) if (count[i] >= 2)++ans; cout << ans << endl; return 0; }