洛谷 P3469 BLO-Blockade
洛谷 P3469 BLO-Blockade
题意
给定一张无向图,求每个点被封锁之后有多少个有序点对
思路
使用 Tarjan 求出割点,有以下几种情况。
- 当前点不是割点,答案为
,即该点与其他所有点不连通。 - 当前点是割点,答案由两部分组成,一是 dfs 树上儿子两两之间不连通,二是 dfs 树上子树内和子树外不连通,答案为
。
注意要加上本身与其他点不连通,
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5, M = 5e5 + 5;
int tot, ver[M << 1], nxt[M << 1], head[N];
int n, m, low[N], dfn[N], siz[N], cnt;
ll ans[N]; bool g[N];
void add(int x, int y) {
ver[++ tot] = y;
nxt[tot] = head[x];
head[x] = tot;
}
void tarjan(int x, int fa) {
low[x] = dfn[x] = ++ cnt, siz[x] = 1;
int s = 0, sum = 0;
for (int i = head[x], y; i; i = nxt[i]) {
y = ver[i];
if (!dfn[y]) {
tarjan(y, x);
siz[x] += siz[y];
if (low[y] >= dfn[x] && fa) g[x] = 1;
if (low[y] >= dfn[x] || !fa)
ans[x] += 1ll * siz[y] * (n - siz[y]), sum += siz[y];
low[x] = min(low[x], low[y]), s ++;
} else if (y != fa)
low[x] = min(low[x], dfn[y]);
}
if (!fa && s >= 2) g[x] = 1;
if (!g[x]) ans[x] = 2ll * (n - 1);
else ans[x] += 1ll * n - 1ll + 1ll * (sum + 1) * (n - sum - 1);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i <= m; i ++) {
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
tarjan(1, 0);
cerr << "g: ";
for (int i = 1; i <= n; i ++)
if (g[i]) cerr << i << ' ';
cerr << '\n';
for (int i = 1; i <= n; i ++)
printf("%lld\n", ans[i]);
return 0;
}
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/18397660,orz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】