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

猜你喜欢

转载自blog.csdn.net/weixin_40588429/article/details/84110926