算法提高课-图论-有向图的强连通分量-AcWing 367. 学校网络:强连通分量、tarjan算法
生活随笔
收集整理的這篇文章主要介紹了
算法提高课-图论-有向图的强连通分量-AcWing 367. 学校网络:强连通分量、tarjan算法
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
文章目錄
- 題目解答
- 題目來源
題目解答
來源:acwing
分析:
第一問:通過tarjan算法求出強連通分量并且縮點后,統(tǒng)計入度為0的點的個數(shù)p即可。
第二問,至少加幾條邊才能使圖變成強連通分量?這個答案是max(p,q)。含義是入度為0,和出度為0的點的個數(shù)的最大值。但特例是,如果只有1個強連通分量,那么不需要加邊,直接輸出0即可。
第二問的問題實際上是:對于任意一個有向無環(huán)圖,至少加多少條邊,才能使之變成強連通分量?記入度為0的點個數(shù)是p,出度為0的點的個數(shù)為q。
答案是max(p, q). 證明過程可以自行搜索。
下面的主要部分還是tarjan的板子
算法提高課-圖論-有向圖的強連通分量-AcWing 1174. 受歡迎的牛:tarjan算法求強連通分量、tarjan算法板子、強連通圖
ac代碼
#include<bits/stdc++.h> using namespace std; const int N = 110, M = 10010; int n; int h[N], e[M], ne[M], idx; int dfn[N], low[N], ts; int stk[N], top; bool in_stk[N]; int id[N], scc_cnt; int din[N], dout[N];void add(int a, int b){e[idx] = b, ne[idx] = h[a], h[a] = idx ++; }void tarjan(int u){dfn[u] = low[u] = ++ ts;stk[++ top] = u, in_stk[u] = true;for(int i = h[u];~i; i = ne[i]){int j = e[i];if(!dfn[j]){tarjan(j);low[u] = min(low[u], low[j]);}else if(in_stk[j]) low[u] = min(low[u], dfn[j]);}if(dfn[u] == low[u]){int y;++ scc_cnt;do{y = stk[top --];in_stk[y] = false;id[y] = scc_cnt;}while(y != u);} }int main(){cin >> n;memset(h, -1, sizeof h);for(int i = 1; i <= n; i ++){int t;while(cin >> t, t) add(i, t);}for(int i = 1; i <= n; i++)if(!dfn[i]) tarjan(i);// 統(tǒng)計出度和入度for(int i = 1; i <= n; i ++ ){for(int j = h[i]; ~j; j = ne[j]){int k = e[j];int a = id[i], b = id[k];if(a != b){dout[a] ++, din[b] ++;}}}int a = 0, b = 0;// 遍歷每個強連通分量,統(tǒng)計縮點后的點的入度和出度for(int i = 1; i <= scc_cnt; i ++){if(!din[i]) a ++;if(!dout[i]) b++;}cout << a << endl;// 只有1個強連通分量,不需要加邊if(scc_cnt == 1) cout << 0 << endl;else cout << max(a, b) << endl; }題目來源
https://www.acwing.com/problem/content/369/
總結(jié)
以上是生活随笔為你收集整理的算法提高课-图论-有向图的强连通分量-AcWing 367. 学校网络:强连通分量、tarjan算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSP认证201512-2消除类游戏[C
- 下一篇: 算法提高课-图论-欧拉回路和欧拉路径-A