树形DP——P2458 [SDOI2006]保安站岗
树形DP——P2458 [SDOI2006]保安站岗
这道题是用花费最少的费用来覆盖全部的点。这类问题的初始化可能有点麻烦。并且这个题目和一个点u以及这个点的父亲儿子有关。所以我们可以通过设置dp[u][0/1/2] 来分别表示当u这个点是用自己或者父亲或者儿子来覆盖u的。当时如果要考虑这个问题的时候说明u这个点的子树全部都覆盖好了。从这个方面来考虑如何进行动态规划。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1500+10;
int cost[maxn];
int dp[maxn][3];
struct Edge{
int v, next;
}edge[maxn<<1];
int head[maxn];
int cnt;
void addEdge(int u, int v)
{
edge[cnt].next = head[u];
edge[cnt].v = v;
head[u] = cnt++;
return;
}
void ini(int n)
{
for(int i = 1; i <= n; i++)
head[i] = -1;
cnt = 0;
}
void dfs(int u, int fa)
{
int flag = 0, flag1 = 0, Min2 = 0x3f3f3f3f;
for(int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if(fa == v) continue;
dfs(v, u);
flag1 = 1;
int Min;
if(dp[v][0] < dp[v][1])
{
flag = 1;
Min = dp[v][0];
}
else
{
Min = dp[v][1];
Min2 = min(Min2, dp[v][0]-dp[v][1]);
}
dp[u][1] += Min;
dp[u][2] += Min;
if(dp[v][2] < Min) Min = dp[v][2];
dp[u][0]+= Min;
}
dp[u][0] += cost[u];
if(!flag1) dp[u][1] = 0x3f3f3f3f;
else if(!flag) dp[u][1] += Min2;
return;
}
int main()
{
int n;
cin >> n ;
ini(n);
for(int i = 1; i <= n; i++)
{
int u, v, w, num;
scanf("%d %d %d", &u, &w, &num);
cost[u] = w;
for(int z = 1; z <= num; z++)
{
scanf("%d", &v);
addEdge(u, v);
addEdge(v, u);
}
}
dfs(1, 0);
cout << min(dp[1][0], dp[1][1]);
return 0;
}

浙公网安备 33010602011771号