作业介绍

E

// f[u][0] u 位置不放置士兵
// f[u][1] u 位置放置士兵

// u 和 v 之间有一条边,u 没有士兵,v必须有
// f[u][0] += f[v][1]

// u 这个点已经有了, v 有没有无所谓
//f[u][1] += min(f[v][0] , f[v][1])

A

// f[i][2] 以 i 为根的子树的最大值,0 代表不来, 1 代表来
// f[i][2]  i 的所有子节点
// 上司不来, 下属可以来或者不来
// f[i][0] +=  max(f[son[i]][0] , f[son[i]][1])
// 上司来, 下属不能来
// f[i][1] += f[son[i]][0]
#include <bits/stdc++.h>
using namespace std;
const int N = 6e3 + 10;
const int M = N * 2;
int n, r[N];
int head[N], ver[M], nxt[M], tot;
int f[N][2];

void add(int u, int v) {
	++tot;
	ver[tot] = v;
	nxt[tot] = head[u];
	head[u] = tot;
}

void dfs(int u, int fa) {
	f[u][1] = r[u];
	// 遍历所有子节点
	for (int i = head[u] ; i ; i = nxt[i]) {
		int v = ver[i];
		if (v == fa)
			continue;
		dfs(v, u);
		// 上司不来, 下属可以来或者不来
		f[u][0] += max(f[v][0], f[v][1]);
		// 上司来, 下属不能来
		f[u][1] += f[v][0];
	}
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> r[i];
	for (int i = 1, u, v; i < n; i++) {
		cin >> u >> v;
		add(u, v), add(v, u);
	}
	dfs(1, 0);
	cout << max(f[1][0], f[1][1]);
	return 0;
}

B

// f[i][j] 以 i 为根,选择 j 门课程
//  的最大学分
// f[i][j] = max(f[i][j-k] + f[v][k])

// 森林, 加一个 root 节点
// m ,加上root 节点, m+1 门课
#include <bits/stdc++.h>
using namespace std;
const int N = 310;
const int M = N * 2;
int a[N];
int f[N][N];
int n, m;
int  siz[N];
int head[N], ver[M], nxt[M], tot;
void add(int u, int v) {
	++tot;
	ver[tot] = v;
	nxt[tot] = head[u];
	head[u] = tot;
}

void dfs(int u, int fa) {
	f[u][1] = a[u];  // 学一门,只能是学自己
	siz[u] = 1;
	for (int i = head[u] ; i; i = nxt[i]) {
		int v = ver[i];
		if (v == fa)
			continue;
		dfs(v, u);
		siz[u] += siz[v];
		// 分组背包
		for (int j = min(m, siz[u]) ; j >= 1; j-- ) {
			// u 这个点是必须放的 -1
			for (int k = 0 ; k <= min(j - 1, siz[v]) ; k++)
				f[u][j] = max(f[u][j], f[v][k] + f[u][j - k]);
		}
	}
}

int main() {
	cin >> n >> m;
	m++; // root
	for (int i = 1 ; i <= n; i++) {
		int x;
		cin >> x >> a[i];
		// 如果 x  为0,直接当做根节点,不用管
		add(x, i), add(i, x);
	}
	dfs(0, -1);
	cout << f[0][m];
	return 0;
}

T

// 换根DP
// f[v] = f[u] - siz[v]-n - siz[v]
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
const int M = N * 2;
#define int long long
int n;
int  siz[N], dep[N], f[N];
int head[N], ver[M], nxt[M], tot;

void add(int u, int v) {
	++tot;
	ver[tot] = v;
	nxt[tot] = head[u];
	head[u] = tot;
}

void dfs(int u, int fa) {
	dep[u] = dep[fa] + 1;
	siz[u] = 1;
	for (int i = head[u] ; i ; i = nxt[i]) {
		int v = ver[i];
		if (v == fa)
			continue;
		dfs(v, u);
		siz[u] += siz[v];
	}
}

void dp(int u, int fa) {
	for (int i = head[u] ; i ; i = nxt[i]) {
		int v = ver[i];
		if (v == fa)
			continue;
		f[v] = f[u] - 2 * siz[v] + n;
		dp(v, u);
	}
}

signed main() {
	cin >> n;
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		add(u, v), add(v, u);
	}
	dfs(1, 0);
	for (int i = 1; i <= n; i++)
		f[1] += dep[i];
	dp(1, 0);
	int res = 1;
	for (int i = 2; i <= n; i++)
		if (f[i] > f[res])
			res = i;
	cout << res;
	return 0;
}

题目

认领作业后才可以查看作业内容。
状态
正在进行…
题目
21
开始时间
2026-5-20 0:00
截止时间
2026-6-30 23:59
可延期
24 小时