poj 1463 Strategic game 树型dp,最小点集覆盖

来源:互联网 发布:北京 补牙 知乎 编辑:程序博客网 时间:2024/04/30 05:00

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