# 題目: UVa 10972 - RevolC FaeLoN
# 題目說明
Koorosh 現在是一名高級顧問,他在沒有你的幫助下解決了 Basm 的問題
跟往常一樣,Basm 征服了一個新地區,叫做 RevolC FaeLoN
為了讓 RevolC FaeLoN 的人民滿意,他想要使該國的道路變成單向來降低事故發生率
他希望每個城市都有一條路能到其他城市,所以他要求 Koorosh 找到需要建造的最少道路數
INPUT:
每筆測資的第一行有兩個整數 n
及 m
, n
代表城市的數量, m
代表道路的數量
接下來會有 m
行,每行有兩個整數 u
及 v
,代表 u
、 v
城市間有一條道路連接
OUTPUT:
輸出需要建造道路的最小數量
# 解題方法
無相圖中的邊雙聯通分量,定向後一定為強連通分量
先找出每個 BCC (Bridge Connected Component) 的 bridge 數量
- 對於 2 個以上 bridge 的 BCC,必定有進來及離開這些城市的路
- 對於 1 個 bridge 的 BCC,總共需要
(x + 1) / 2
條道路才能全部連接 (x 為 1 個 bridge 的 BCC 的數量) - 對於 0 個 bridge 的 BCC,總共需要
y
條道路才能全部連接 (y 為 0 個 bridge 的 BCC 的數量)
所以總共需要(x + 1) / 2 + y
條道路
如果只有一個 BCC 且 bridge 為 0,則不需要建造道路,輸出 0
# 參考程式碼
- 0 個 bridge 的 BCC,用
vector<int> bridge
找出 - 1 個 bridge 的 BCC,用每個點的
low
值找出
#include <iostream> | |
#include <vector> | |
#include <algorithm> | |
#include <map> | |
using namespace std; | |
vector< vector<int> > G; | |
vector<int> dfn, low, bridge; | |
int dep; | |
void dfs(int u, int par) | |
{ | |
dfn[u] = low[u] = ++dep; | |
for (auto& v : G[u]) | |
{ | |
if (!dfn[v]) | |
{ | |
dfs(v, u); | |
low[u] = min(low[u], low[v]); | |
} | |
else if (v != par) low[u] = min(low[u], low[v]); | |
if (low[v] > low[u]) bridge.emplace_back(v), bridge.emplace_back(u); | |
} | |
} | |
int main() | |
{ | |
ios::sync_with_stdio(false); | |
cin.tie(nullptr); | |
cout.tie(nullptr); | |
int n, m, a, b; | |
while (cin >> n >> m) | |
{ | |
// init | |
G.assign(n + 1, vector<int>()); | |
dfn.assign(n + 1, 0); | |
low.assign(n + 1, 0); | |
bridge.clear(); | |
dep = 0; | |
int con1 = 0, con0 = 0; | |
// store data | |
while (m--) | |
{ | |
cin >> a >> b; | |
G[a].emplace_back(b); | |
G[b].emplace_back(a); | |
} | |
// find bridge connected component | |
for (int i = 1; i <= n; ++i) | |
if (!dfn[i]) | |
{ | |
size_t s = bridge.size(); | |
dfs(i, -1); | |
if (s == bridge.size()) ++con0; | |
} | |
// solve | |
if (bridge.size() == 0 && con0 == 1) cout << "0\n"; | |
else | |
{ | |
map<int, int> m; | |
for (int i = 1; i <= n; ++i) | |
{ | |
m[low[i]] += 0; | |
for (auto& v : G[i]) if (low[v] != low[i]) ++m[low[i]]; | |
} | |
for (auto& [__, de] : m) if (de == 1) ++con1; | |
cout << con0 + (con1 + 1) / 2 << "\n"; | |
} | |
} | |
return 0; | |
} |
# 參考文章:
https://www.larrysprognotes.com/UVa%20-%2010972/