題面
題意:一棵樹,選最少的點使得所有點都被覆蓋奇數次
選一個點會覆蓋它自身和相鄰的點
爲點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;
}