题目大意

 
题目链接:[刷油漆][1]

题目分析

 
状态优化。

//dp[node][i]表示以node为根的子树中选择i个节点,且节点相互连通,所能达到的value和的最大值。
//注意i要从大到小进行枚举,且j一定小于i,不能等于i,因为node节点必须被占用
for (int i = M; i >= 2; i--) {
    for (int j = 1; j < i; j++) {
        dp[node][i] = dp[node][i] > dp[node][i - j] + dp[v][j] ? dp[node][i] : dp[node][i - j] + dp[v][j];
        }
}

 实现

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
struct Edge {
	int to;
	int next;
};

int gNodeValue[105];
int dp[105][105];
int gHead[105];
bool gVisited[105];
int gValue[105];
Edge gEdges[220];
int gEdgeIndex;

void InsertEdge(int u, int v) {
	int e = gEdgeIndex++;
	gEdges[e].to = v;
	gEdges[e].next = gHead[u];
	gHead[u] = e;

	e = gEdgeIndex++;
	gEdges[e].to = u;
	gEdges[e].next = gHead[v];
	gHead[v] = e;
}
int min(int a, int b) {
	return a < b ? a : b;
}
void Dfs(int node, int m) {
	gVisited[node] = true;
	int e = gHead[node];
	dp[node][1] = gValue[node];
	for (e; e != -1; e = gEdges[e].next) {
		int v = gEdges[e].to;
		if (!gVisited[v]) {
			Dfs(v, m);
			for (int i = m; i >= 2; i--) {
				for (int j = 1; j < i; j++) {
					dp[node][i] = dp[node][i] > dp[node][i - j] + dp[v][j] ? dp[node][i] : dp[node][i - j] + dp[v][j];
				}
			}
			
		}
	}	
}

void Init() {
	memset(gValue, 0, sizeof(gValue));
	memset(dp, 0, sizeof(dp));
	memset(gValue, false, sizeof(gVisited));
	memset(gEdges, -1, sizeof(gEdges));
	gEdgeIndex = 0;
	memset(gSuccessorNum, 0, sizeof(gSuccessorNum));
	memset(gHead, -1, sizeof(gHead));
}

int main() {
	int n, m;
	Init();
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &gValue[i]);
	}
	int u, v;
	for (int i = 1; i < n; i++) {
		scanf("%d %d", &u, &v);
		InsertEdge(u, v);
	}
	Dfs(1, m);
	printf("%d\n", dp[1][m]);
	return 0;
}

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-26
  • 2022-12-23
  • 2021-10-30
  • 2022-12-23
  • 2021-07-21
猜你喜欢
  • 2022-01-05
  • 2022-02-25
  • 2021-07-04
  • 2022-12-23
  • 2021-12-18
  • 2021-08-29
相关资源
相似解决方案