您的位置:首页 > 其它

uvalive2038(树形DP基础题)

2016-04-20 17:35 429 查看
题目大意:

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

思路:

树形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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: