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

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


你可能感兴趣的:(struct)