题目:http://poj.org/problem?id=1463
题意:给一颗树,用最少的点把所有的边覆盖了。可以用动态规划,也可以用最小点集覆盖(最裸的题目)。
很水的一个题目,又是一个树的遍历,哎!去网上搜的树型DP。。。。。。。。。既然已经做了,就写个解题吧!
解题:这个题目和poj3659差不多,这个是覆盖边,那个是覆盖点(poj3659解题报告),现在只说用dp的解法。
每个点有两个状态:
1、利用点i去覆盖和它相连的边,dp[i][1]表示;
2、不利用点i去覆盖和它相连的边,dp[i][0]表示;
状态转移方程是:
dp[i][1]+=min(dp[v][0],dp[v][1]);
dp[i][0]+=dp[v][1];(v是i的孩子)。
代码:
#include <stdio.h> #include <string.h> #include <iostream> #include <vector> using namespace std; #define N 10005 struct Node{ int v,next; }node[N<<1]; int headnod[N]; bool vist[N]; int num,ans,k; int dp[N][3]; void Add(int u,int v) { node[k].v=v; node[k].next=headnod[u]; headnod[u]=k++; } void init() { int i,j,x,y,x_num; k=1; memset(headnod,0,sizeof(headnod)); memset(vist,true,sizeof(vist)); for(i=0;i<num;i++) { scanf("%d:(%d)",&x,&x_num); for(j=0;j<x_num;j++) { scanf("%d",&y); Add(x,y); Add(y,x); } } } void dfs(int key) { vist[key]=false; dp[key][0]=0; dp[key][1]=1; for(int i=headnod[key];i;i=node[i].next) { int v=node[i].v; if(vist[v]) { dfs(v); dp[key][0]+=dp[v][1]; dp[key][1]+=min(dp[v][0],dp[v][1]); } } } int main() { //freopen("/home/acm/JPY/input.txt","r",stdin); while(cin>>num) { init(); dfs(1); cout<<min(dp[1][1],dp[1][0])<<endl; } return 0; }