L

直将所有敌袭存进一个队列,一天一天模拟即可,最终点1的值的相反数就是答案。

#include <bits/stdc++.h>
using namespace std;
// 2024 OneWan
vector<int> adj[100005];
int fa[100005];
long long val[100005];
long long temp[100005];
void dfs(int u, int p) {
	fa[u] = p;
	for (auto &to : adj[u]) {
		if (to == p) continue;
		dfs(to, u);
	}
}
void solve() {
	int n;
	cin >> n;
	for (int i = 1 ; i <= n ; i++) {
		adj[i].resize(0);
	}
	for (int i = 1 ; i < n ; i++) {
		int u, v;
		cin >> u >> v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	queue<int> que;
	for (int i = 1 ; i <= n ; i++) {
		temp[i] = 0;
		cin >> val[i];
		if (val[i] < 0) {
			que.push(i);
		}
	}
	dfs(1, 0);
	set<int> st;
	long long ans = 0;
	while (!que.empty()) {
		while (!que.empty()) {
			int x = que.front();
			que.pop();
			if (x <= 1) continue;
			st.insert(fa[x]);
			temp[fa[x]] += val[x];
			val[x] = 0;
		}
		while (!st.empty()) {
			int x = *st.begin();
			st.erase(st.begin());
			if (x == 1) {
				ans = max(ans, -temp[x]);
				temp[x] = 0;
				continue;
			}
			if (llabs(temp[x]) > val[x]) {
				val[x] = temp[x] + val[x];
			}
			if (val[x] < 0) {
				que.push(x);
			}
			temp[x] = 0;
		}
	}
	cout << ans << "\n";
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		solve();
	}
	return 0;
}

M

给定 个点和 条边的非联通图,问不使用这 条边能不能构成一个 个点的连通图,如果可以输出具体方案。

使用并查集将输入的非连通图进行连通块分类,如果有两个连通块 ,只需要 中的点连接 中的一点 和 中 的点连接 中的一点就能构成一个连通图。

可以证明最小数量为 条边。我们只需要 的第一个点不连接即可。

#include <bits/stdc++.h>
using namespace std;

// 2024 OneWan

int f[1000005];

int find(int x) {
	return f[x] == x ? x : f[x] = find(f[x]);
}
void merge(int x, int y) {
	x = find(x);
	y = find(y);
	if (x == y) return;
	f[x] = y;
}
void solve() {
	int n, m;
	cin >> n >> m;
	iota(f, f + n + 1, 0);
	for (int i = 0 ; i < m ; i++) {
		int u, v;
		cin >> u >> v;
		merge(u, v);
	}
	vector<int> a;
	for (int i = 1 ; i <= n ; i++) {
		if (find(i) == i) {
			a.push_back(i);
		}
	}
	cout << "Yes\n";
	cout << n - 1 << "\n";
	for (int i = 1 ; i <= n ; i++) {
		if (i == a[0]) continue;
		if (find(i) == a[0]) {
			cout << i << " " << a[1] << "\n";
		} else {
			cout << i << " " << a[0] << "\n";
		}
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		solve();
	}
	return 0;
}