uvalive2038(树形DP基础题)

题目大意:
给定一棵树,要求选择尽量少的点,使得没有被选择的点都可以至少和一个已经选择的点相邻。

思路:
树形DP。
类似于01背包问题。
树上的结点要么选要么不选。
dp[i][0]表示第i个结点不选
那么dp[i][0] += dp[j][1] 其中j是i的子树的根节点。
dp[i][1]表示第i个结点要选
那么dp[i][1] += min(dp[j][1],dp[j][0])

发现一个问题:
9
0:(3) 1 2 3
2:(1) 4
4:(1) 5
5:(3) 6 7 8
这组数据的答案是2 但是跑出来是3。
不懂。。。
代码:

#include <iostream>
using namespace std;
#include <cstring>
#include <cstdio>
const int maxn = 1510;
int n;
char str[120];
int tot;
int head[maxn];
int d[maxn][3];
struct Edge {
    int t,ne;
}edge[maxn *(maxn - 1)/2];

void addedge(int u,int v) {
    edge[tot].t = v;
    edge[tot].ne = head[u];
    head[u] = tot++;
}
void dfs(int u,int father) {
    d[u][0] = 0;
    d[u][1] = 1;
    for(int e = head[u];e != - 1; e = edge[e].ne) {
        int v = edge[e].t;
        if(v == father)
            continue;
        dfs(v,u);
        d[u][0] += d[v][1];
        d[u][1] += min(d[v][0],d[v][1]);
    }
}
int main() {

    while(scanf("%d",&n) !=EOF) {
        tot = 0;
        memset(head,-1,sizeof(head));
        for(int i = 0; i < n ; i++) {
            scanf("%s",str);
            int flag = 0;
            int start,num;
            int e;
            for(int j = 0; str[j]!= '\0';) {
                if(str[j] >= '0' && str[j] <= '9') {
                    int temp = str[j] - '0';
                    j++;
                    while(str[j] >= '0' && str[j] <= '9') {
                        temp = temp * 10 + (str[j] - '0');
                        j++;
                    }
                    if(flag == 0) {
                        start = temp;
                        flag ++;
                    }
                    else 
                        num = temp;
                }
                else 
                    j++;
            }
            for(int j = 0; j < num; j++) {
                scanf("%d",&e);
                addedge(start,e);
                addedge(e,start);
            }
        }
        dfs(0,-1);
        printf("%d\n",min(d[0][0],d[0][1]));
    }

    return 0;
}

你可能感兴趣的:(uvalive2038(树形DP基础题))