[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;
}
posted @ 2021-02-24 10:43  zkdxl  阅读(42)  评论(0编辑  收藏  举报