题目: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;
}