(tarjan/割點)[POI2008]BLO-Blockade
阿新 • • 發佈:2018-12-21
https://www.luogu.org/problemnew/show/P3469
在Byteotia有n個城鎮。 一些城鎮之間由無向邊連線。 在城鎮外沒有十字路口,儘管可能有橋,隧道或者高架公路(反正不考慮這些)。每兩個城鎮之間至多隻有一條直接連線的道路。人們可以從任意一個城鎮直接或間接到達另一個城鎮。 每個城鎮都有一個公民,他們被孤獨所困擾。事實證明,每個公民都想拜訪其他所有公民一次(在主人所在的城鎮)。所以,一共會有n*(n-1)次拜訪。不幸的是,一個程式設計師總罷工正在進行中,那些程式設計師迫切要求購買某個軟體。作為抗議行動,程式設計師們計劃封鎖一些城鎮,阻止人們進入,離開或者路過那裡。正如我們所說,他們正在討論選擇哪些城鎮會導致最嚴重的後果。編寫一個程式:讀入Byteotia的道路系統,對於每個被決定的城鎮,如果它被封鎖,有多少訪問不會發生,輸出結果。
分別處理點去掉後對圖連通性沒有影響的點和割點(去掉後的每個聯通塊大小相乘相加,注意ll)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 10; const int maxm = 5e5 + 10; vector<int> E[maxn]; vector<ll> node[maxn]; int dfn[maxn], low[maxn], state[maxn], tot, cnt[maxn]; int n, m, a, b; void tarjan(int u, int pre) { dfn[u] = low[u] = ++tot; cnt[u]++; int tmp = 0; for(int v : E[u]) { if(dfn[v] == 0) { tarjan(v, u); cnt[u] += cnt[v]; low[u] = min(low[u], low[v]); if (low[v] >= dfn[u]) { state[u] = true; tmp += cnt[v]; node[u].emplace_back(cnt[v]); } } else if(v != pre) low[u] = min(low[u], dfn[v]); } if(state[u] && n - tmp - 1 != 0) node[u].emplace_back(n - tmp - 1); } int main() { scanf("%d%d", &n, &m); register int i, j, k; for (i = 0; i < m; i++) { scanf("%d%d", &a, &b); E[a].emplace_back(b); E[b].emplace_back(a); } tarjan(1, 0); for (i = 1; i <= n; i++) { ll ans = 2 * n - 2; if(node[i].size() != 0 && node[i].size() != 1) { for (j = 0; j < node[i].size(); j++) { for (k = j + 1; k < node[i].size(); k++) ans += 2 * node[i][j] * node[i][k]; } } printf("%lld\n", ans); } // system("pause"); }