标签:
http://acm.hdu.edu.cn/showproblem.php?pid=1054
4 0:(1) 1 1:(2) 2 3 2:(0) 3:(0) 5 3:(3) 1 4 2 1:(1) 0 2:(0) 0:(0) 4:(0)
1 2
/**
hdu1054 树形dp
题目大意:给定一棵树求最小边覆盖的点数
解题思路:可以用二分图的最大匹配做,最大匹配数就是最小边覆盖。也可以树形dp:
dp[u][0]表示以u为根节点的树u点不取的数目,dp[u][1]表示以u为根节点的树u点取的数目.
状态转移方程:dp[u][0]+=dp[v][1];
dp[u][1]+=min(dp[v][0],dp[v][1]);
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=1550;
int head[maxn],ip;
int dp[maxn][2],n;
struct note
{
int v,next;
}edge[maxn*4];
void init()
{
memset(head,-1,sizeof(head));
ip=0;
}
void addedge(int u,int v)
{
edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
}
void dfs(int u,int pre)
{
dp[u][1]=1;
dp[u][0]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre) continue;
dfs(v,u);
dp[u][0]+=dp[v][1];
dp[u][1]+=min(dp[v][0],dp[v][1]);
}
}
int main()
{
while(~scanf("%d",&n))
{
init();
for(int i=0;i<n;i++)
{
int u,k;
scanf("%d:(%d)",&u,&k);
u++;
for(int j=0;j<k;j++)
{
int v;
scanf("%d",&v);
v++;
addedge(u,v);
addedge(v,u);
}
}
memset(dp,0,sizeof(dp));
dfs(1,-1);
printf("%d\n",min(dp[1][0],dp[1][1]));
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/43606653