Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

P3469 [POI2008]BLO-Blockade

P3469 [POI2008]BLO-Blockade

考虑如果一个点是割点,那么被割出去的所有点到其他所有点都被割开了。如果不是割点,答案为 $2(n -1)$ 。

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <cstdio>
#include <vector>
using namespace std;
template <class Type>
void read(Type &x)
{
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9')
c == '-' && (flag = true);
x = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
x = (x << 3) + (x << 1) + c - '0';
if (flag) x = ~x + 1;
}
template <class Type, class ...rest>
void read(Type &x, rest &...y) { read(x), read(y...); }
template <class Type>
void write(Type x)
{
if (x < 0) putchar('-'), x = ~x + 1;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <class Type>
void chkmin (Type &x, Type k) { if (k < x) x = k; }
typedef long long LL;
const int N = 1e5 + 10;
LL ans[N];
bool cut[N];
int n, m, sz[N];
int stmp, dfn[N], low[N];
vector <int> g[N];
void tarjan (int x, int &rt)
{
dfn[x] = low[x] = ++stmp;
int son = 0, tot = 0;
sz[x] = 1;
for (int i : g[x])
if (dfn[i])
chkmin(low[x], dfn[i]);
else
{
tarjan(i, rt);
chkmin(low[x], low[i]);
son++;
sz[x] += sz[i];
if (low[i] >= dfn[x])
{
tot += sz[i];
ans[x] += (LL)sz[i] * (n - sz[i]);
if (x ^ rt || ++son > 1) cut[x] = true;
}
}
if (cut[x]) ans[x] += (LL)(n - tot - 1) * (tot + 1) + n - 1;
else ans[x] = n - 1 << 1;
}
int main ()
{
read(n), read(m);
for (int a, b; m; m--)
{
read(a, b);
g[a].push_back(b), g[b].push_back(a);
}
for (int i = 1; i <= n; i++)
if (!dfn[i]) tarjan(i, i);
for (int i = 1; i <= n; i++) write(ans[i]), puts("");
return 0;
}