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]));
}
posted @ 2020-09-09 21:37  INFP  阅读(154)  评论(0编辑  收藏  举报