分析:
给出一棵N个节点的树,一共N-1条边,每个节点都有其价值,要求从中选出互相连接的M个节点(包括节点1)使得其价值和最大。题解:
设dp[i][j]为第i个节点下的选择j个节点时(包括第i个节点)的最大价值。我们先把每一个dp[i][1]都初始化每个节点自己的价值,表示单独选择i节点时候得到的最大价值。然后从节点1开始DFS(题意要求必须包括节点1),每搜到它下面一个节点,再以那个节点进行DFS。DFS返回这个节点下的子节点数目。然后更新DP数组:
int dfs(int u, int m) //计算节点个数,同时更新dp数组
{
int sons = 1; //子节点个数初始化为1,即自己本身
int num;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v = edge[i].v; //取出相连的第一个节点
num = dfs(v, m-1); //计算v节点下一共有多少个子节点,同时也会更新dp[v]下面的最大值。
for(int j=m;j>=1;j--)
{
for(int k=1; k<=num && k<j; k++)
{
dp[u][j] = MAX( dp[u][j], dp[v][k]+dp[u][j-k] );
//j表示u节点下一共取多少个节点,k表示v节点下一共取多少个节点,这样遍历一遍更新出最大的dp[u][j]值。
}
}
sons += num;
}
return sons;//返回节点数
}
- AC代码:
/*************************************************************************
> File Name: 1055.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
> Created Time: 2016年10月07日 星期五 14时21分56秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;
#define MaxN 110
#define MaxM MaxN*2
#define INF 0x3f3f3f3f
#define bug cout<<88888888<<endl;
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
int N, M;
int dp[MaxN][MaxN];
struct Edge
{
int u,v;
int next;
}edge[MaxM];
int head[MaxN];
int cont;
void init()
{
CLR(dp);
MST(head, -1);
cont = 0;
}
void add(int u, int v)
{
edge[cont].v = v;
edge[cont].next = head[u];
head[u] = cont++;
}
int dfs(int u, int m)
{
int sons = 1;
int num;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v = edge[i].v;
num = dfs(v, m-1);
for(int j=m;j>=1;j--)
{
for(int k=1; k<=num && k<j; k++)
{
dp[u][j] = MAX( dp[u][j], dp[v][k]+dp[u][j-k] );
}
}
sons += num;
}
return sons;
}
int main()
{
while(~scanf("%d%d", &N, &M))
{
init();
for(int i=1;i<=N;i++)
{
scanf("%d", &dp[i][1]);
}
int a, b;
for(int i=1;i<N;i++)
{
scanf("%d%d", &a, &b);
add(a, b);
}
dfs(1, M);
cout << dp[1][M] << endl;
}
}