Centroids
Centroids
换根dp
SCUACM2022集训前训练-动态规划 - Virtual Judge (vjudge.net)
- 重心只有 1 个 或 2 个
- 待补
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 4e5 + 10;
int n, root;
vector<vector<int> > G(N);
int cnt[N], sz[N], f[N][2], res[N];
void add(int u, int v)
{
G[u].push_back(v);
}
//找重心,以重心为根建树,好处是所有结点的子树都是满足条件的
//只需判断能否通过改变结点上方的 <=n/2 的子树来使结点上方的结点 <= n/2
void dfs(int u, int fa)
{
sz[u] = 1;
bool flag = true;
for (auto v : G[u])
{
if (v == fa)
continue;
dfs(v, u);
sz[u] += sz[v];
if (sz[v] > n / 2)
flag = false;
}
if (n - sz[u] > n / 2)
flag = false;
if (flag)
root = u;
}
void dfs1(int u, int fa)
{
sz[u] = 1;
for (auto v : G[u])
{
if (v == fa)
continue;
dfs(v, u);
sz[u] += sz[v];
if (sz[v] > n / 2)
continue;
if (sz[v] > f[u][0])
f[u][1] = f[u][0], f[u][0] = sz[v];
else if (sz[v] > f[u][1])
f[u][1] = sz[v];
}
}
void dfs2(int u, int fa, int maxn)
{
cnt[u] = maxn;
if (n - sz[u] - cnt[u] <= n / 2 || u == root)
res[u] = 1;
for (auto v : G[u])
{
if (v == fa)
continue;
if (n - sz[u] <= n / 2)
maxn = max(maxn, n - sz[u]);
if (f[u][0] == sz[v])
dfs2(v, u, max(maxn, f[u][1]));
else
dfs2(v, u, max(maxn, f[u][0]));
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
add(u, v), add(v, u);
}
dfs(1, -1);
dfs1(root, -1);
dfs2(root, -1, 0);
for (int i = 1; i <= n; i++)
cout << res[i] << " ";
cout << endl;
return 0;
}