1. 程式人生 > >(tarjan/割點)[POI2008]BLO-Blockade

(tarjan/割點)[POI2008]BLO-Blockade

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");
}