标签:
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