Luogu P3469 [POI2008]BLO-Blockade
P3469 [POI2008]BLO-Blockade - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
图
在
(一个);- 在
在搜索树上的后代 中,满足 的,搜索树上以 为根的子树上的节点集(零个到多个); - 上面那两块除去之后剩余所有节点的集合(一个)。
只要在 tarjan 的时候统计就行了。
并不需要统计割点,但是确实运用了这个思想。
注意,我的代码中 tarjan 可能写的有点奇怪,可以看这篇文章中的说明。
/*
* @Author: crab-in-the-northeast
* @Date: 2022-10-13 00:45:34
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2022-10-13 01:38:31
*/
#include <bits/stdc++.h>
#define int long long
inline int read() {
int x = 0;
bool flag = true;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
flag = false;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
if(flag)
return x;
return ~(x - 1);
}
const int maxn = (int)1e5 + 5;
std :: vector <int> G[maxn];
int siz[maxn], low[maxn], dfn[maxn], ans[maxn], times;
int n;
inline bool gmi(int &a, int b) {
return b < a ? a = b, true : false;
}
inline void tarjan(int u) {
dfn[u] = low[u] = ++times;
siz[u] = 1;
ans[u] = n - 1; // 第一种连通块的贡献
int tot = n - 1; // 第三种连通块的大小,为 n-第一种连通块的大小-第二种的
// 这里先把第一种的减去(就是1),一会还会减掉第二种的
for (int v : G[u]) {
if (!dfn[v]) {
tarjan(v);
siz[u] += siz[v];
gmi(low[u], low[v]);
if (low[v] == dfn[u]) {
ans[u] += siz[v] * (n - siz[v]); // 第二种连通块
tot -= siz[v]; // 第三种连通块大小减去第二种的
}
} else
gmi(low[u], dfn[v]);
}
ans[u] += tot * (n - tot); // 第三种连通块
}
signed main() {
n = read();
int m = read();
while (m--) {
int u = read(), v = read();
G[u].push_back(v);
G[v].push_back(u);
}
tarjan(1);
for (int u = 1; u <= n; ++u)
printf("%lld\n", ans[u]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】