P2866
考虑设置三种状态
\(e[x].to=v\)
\(f[x][0]\)被自己守,三种情况都可以,\(f[x][0]+=min(f[v][1],f[v][2],f[v][0])\)
\(f[x][1]\)被父亲守,\(f[x][1]+=min(f[v][0],f[v][2])\)
枚举被哪个儿子守,利用已经被计算好的\(f[x][1]\)
\(f[x][2]\)被儿子守,\(f[x][2]=min(f[x][2],f[x][1]-min(f[v][0],f[v][2])+f[v][0])\)
#include<cstdio>
#include<iostream>
#define N 100001
#define inf 0x3f3f3f3f
using namespace std;
inline int read(){
int x = 0;char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) x = x*10+c-48,c=getchar();
return x;
}
struct edge{int to,next;}e[N<<1]; int tot,head[N];
inline void add(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;}
int n,f[N][3];//0表示被自己染了,1表示被儿子染了,2表示被父亲染了
inline int min(int a,int b){return a < b ? a : b;}
void dfs(int x,int fa){
f[x][0] = 1;f[x][2] = inf;
for(int i = head[x];i;i = e[i].next){
int v = e[i].to;
if(v == fa) continue;
dfs(v,x);
f[x][0] += min(f[v][0],min(f[v][1],f[v][2]));
f[x][1] += min(f[v][0],f[v][2]);
}
for(int i = head[x];i;i = e[i].next){
int v = e[i].to; if(v == fa) continue;
f[x][2] = min(f[x][2],f[x][1] - min(f[v][0],f[v][2]) + f[v][0]);
}
}
int main(){
n = read();int x,y;
for(int i = 1;i < n;++i){
x = read(); y = read();
add(x,y); add(y,x);
}
dfs(1,-1);
printf("%d\n", min(f[1][0],f[1][2]));
}