题面
题意:一棵树,选最少的点使得所有点都被覆盖奇数次
选一个点会覆盖它自身和相邻的点
为点x设4个状态,分别表示x选或不选,仅考虑x的子树,x是否被覆盖
若某个点不选,则每个儿子都要被覆盖,反之亦然
就可以转移了,虽然有一丢丢烦
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))
typedef long long LL;
const int N=100100;
int n;
int to[N],nex[N],head[N],cnt;
// 选 不选
LL a[N],b[N];//亮
LL c[N],d[N];//不亮
int fa[N];
void add(int u,int v)
{
to[++cnt]=v;
nex[cnt]=head[u];
head[u]=cnt;
}
void dfs(int x)
{
a[x]=1;
d[x]=0;
b[x]=c[x]=n;
for(int h=head[x];h;h=nex[h])
if(to[h]!=fa[x])
{
fa[to[h]]=x;
dfs(to[h]);
LL hy=a[x];
a[x]=min(hy+d[to[h]],c[x]+c[to[h]]);
c[x]=min(c[x]+d[to[h]],hy+c[to[h]]);
hy=b[x];
b[x]=min(hy+b[to[h]],d[x]+a[to[h]]);
d[x]=min(d[x]+b[to[h]],hy+a[to[h]]);
}
}
int main()
{
while(1)
{
cin>>n;
if(!n)
return 0;
mmst(head,0);
cnt=0;
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1);
cout<<min(a[1],b[1])<<endl;
}
return 0;
}