电子眼【树形dp】
题目大意:
题目链接:http://10.156.17.250/JudgeOnline/showproblem?problem_id=2119 (学校局域网)
在一棵树中选择一些点使得每条边至少与一个选择的点相邻。
思路:
很显然的树形。
设表示以节点为根,选或不选这个点的最少选择数量。
显然如果不选择这个点,那么这个点的所有儿子节点都必须选,否则这个点的子节点选择或不选都可以。
方程如下
特别的,当时直接输出1就可以了。
代码:
#include <cstdio>
#include <iostream>
using namespace std;
const int N=100010;
int n,x,y,tot,in[N],head[N],f[N][2];
struct edge
{
int next,to;
}e[N*2];
void add(int from,int to)
{
e[++tot].to=to;
e[tot].next=head[from];
head[from]=tot;
}
void dp(int x,int fa)
{
f[x][1]=1;
for (int i=head[x];~i;i=e[i].next)
{
int y=e[i].to;
if (y==fa) continue;
dp(y,x);
f[x][0]+=f[y][1];
f[x][1]+=min(f[y][0],f[y][1]);
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d",&n);
if (n==1) return !printf("1");
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
in[x]++;
in[y]++;
}
dp(1,0);
printf("%d",min(f[1][0],f[1][1]));
return 0;
}