[CF1375G] Tree Modification
\(\text{Problem}:\)题目链接
\(\text{Solution}:\)
非常巧妙的一道全局思维题。
观察操作的性质。假设当前 \(a\) 为根,相当于将 \(a\) 的不包含 \(c\) 的子树全部接到 \(c\) 上,然后此时以 \(c\) 为根,\(a\) 为 \(c\) 的孩子节点。设 \(dep_{root}=0\),我们发现,一次操作使得 \(dep_{a}\) 从 \(0\) 变为 \(1\),操作前以 \(a\) 为根的 \(c\) 的子树内节点的 \(dep\) 都减去 \(2\)。这说明一次操作只会使得一个节点的深度的奇偶性发生变化。
考虑树上节点深度奇偶性变化的实质。我们知道树是一个二分图,那么可以对树进行黑白染色,深度为偶数和奇数的节点的颜色不相同。现在问题转化为:一次操作可以改变一个节点的颜色,问最少多少次操作可以使得黑点或白点出现 \(n-1\) 次。
那么一遍 \(DFS\) 就可以得到答案。
\(\text{Code}:\)
#include <bits/stdc++.h>
#pragma GCC optimize(3)
#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
using namespace std; const int N=400010;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
int n,W,B;
int head[N],maxE; struct Edge { int nxt,to; }e[N<<1];
inline void Add(int u,int v) { e[++maxE].nxt=head[u]; head[u]=maxE; e[maxE].to=v; }
void DFS(int x,int fa,int dep)
{
if(dep&1) W++;
else B++;
for(ri int i=head[x];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
DFS(v,x,dep+1);
}
}
signed main()
{
n=read();
for(ri int i=1;i<n;i++)
{
int u,v;
u=read(), v=read();
Add(u,v), Add(v,u);
}
DFS(1,0,0);
printf("%lld\n",min(W,B)-1);
return 0;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。