poj 1463Strategic game【树形dp】

题目链接:http://poj.org/problem?id=1463

题意:给你一棵树, 求用最小的点覆盖所有的边。

思路:
树上的dp,对于一个节点i,dp[i][1]表示以i为根节点选择i点的最优解,dp[i][0]为不选择i的解,对于所有的j是i的儿子节点,dp[i][0] += dp[j][1],dp[i][1] += min(dp[j][1],dp[j][0]);

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <string>

using namespace std;

struct Edge
{
    int to, next;
}edge[5010000];

int tol = 0;
int head[2010];

void init()
{
    memset(head, -1, sizeof(head));
}

void addedge(int u,int v)
{
    edge[tol].to = v;
    edge[tol].next = head[u];
    head[u] = tol++;
}

int n, vis[2010];
int dp[2010][2];

void dfs(int root)
{
    dp[root][0] = 0;
    dp[root][1] = 1;

    if (vis[root])
        return;
    vis[root] = 1;

    for (int i = head[root];i != -1;i = edge[i].next)
    {
        int v = edge[i].to;
        if (!vis[v])
        {
            dfs(v);
            dp[root][0] += dp[v][1];
            dp[root][1] += min(dp[v][0], dp[v][1]);
        }
    }
}

int main()
{
    while (scanf("%d", &n) != EOF)
    {
        init();
        int root;
        memset(dp, 0, sizeof(dp));
        memset(vis, 0, sizeof(vis));

        for (int i = 1;i <= n;i++)
        {
            int m, v, num;
            scanf("%d:(%d)", &m, &num);

            if (i == 1) root = m;

            while (num--)
            {
                scanf("%d", &v);
                addedge(m, v);
                addedge(v, m);
            }
        }

        dfs(root);

        int ans = min(dp[root][0], dp[root][1]);
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(dp,poj)