比赛链接:

https://codeforces.com/contest/1689

C. Infected Tree

题意:

\(n\) 个节点的二叉树,根节点被感染了。每一秒依次发生下列两个操作:
1.可以选择一个未被感染的节点,将它从树中删除
2.被感染的节点感染自己未被删除的子节点
问最多能保护多少子节点不被感染。

思路:

定义 \(dp[i]\)\(i\) 被感染后,最多能保护多少子节点不被感染。那么答案就是 \(dp[1]\)
对于一个节点 \(u\) 来说。
如果它只有一个子节点,那么肯定选择将它的子节点删除,来保护剩余的子节点。
如果它有两个子节点,那么考虑删除哪个子节点更优,得到转移方程 \(dp[u] = max(dp[v_1] + sz[v_2] - 1, dp[v_2] + sz[v_1] - 1)\)。(\(sz[u]\) 表示以 \(u\) 为根的子树大小)

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL T;
void solve(){
	LL n;
	cin >> n;
	vector <LL> g[n + 1];
	for (int i = 0; i < n - 1; i ++ ){
		LL u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector <LL> sz(n + 1), dp(n + 1);
	function <void(LL, LL)> dfs = [&] (LL u, LL p){
		sz[u] = 1;
		vector <LL> t;
		for (auto v : g[u]){
			if (v == p) continue;
			dfs(v, u);
			t.push_back(v);
			sz[u] += sz[v];
		}
		if (t.size() == 1)
			dp[u] += sz[t[0]] - 1;
		else if (t.size() == 2)
			dp[u] = max( sz[t[0]] - 1 + dp[t[1]], sz[t[1]] - 1 + dp[t[0]]);
	};
	dfs(1, 0);
	cout << dp[1] << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	cin >> T;
	while (T -- )
		solve();
	return 0;
}

D. Lena and Matrix

题意:

给定一个只包含 'B' 和 'W' 的矩阵,求出一个位置,让它到所有 'B' 的位置的曼哈顿距离的最大值最小。

思路:

显然,要找 'B' 最外围的点,不需要全部求出来,只用考虑四个角的点。
正对角线上最远的两个点就是 \(x + y\) 最大和最小的两个点,副对角线上最远的两个点就是 \(x - y\) 最大和最小的两个点。先求出这四个点。
然后遍历所有位置,找到最小值。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL INF = 1e18;
void solve(){
	LL n, m;
	cin >> n >> m;
	vector <LL> mx(4);
	mx[0] = INF;
	mx[1] = -INF;
	mx[2] = INF;
	mx[3] = -INF;
	for (LL i = 1; i <= n; i ++ ){
		for (LL j = 1; j <= m; j ++ ){
			char c;
			cin >> c;
			if (c == 'B'){
				mx[0] = min(mx[0], i + j);
				mx[1] = max(mx[1], i + j);
				mx[2] = min(mx[2], i - j);
				mx[3] = max(mx[3], i - j);
			}
		}
	}
	function<LL(LL, LL)> cal = [&] (LL x, LL y){
		LL ans = -INF;
		for (int i = 0; i < 2; i ++ )
			ans = max(ans, abs(x + y - mx[i]));
		for (int i = 2; i < 4; i ++ )
			ans = max(ans, abs(x - y - mx[i]));
		return ans;
	};
	LL x = 1, y = 1;
	for (int i = 1; i <= n; i ++ ){
		for (int j = 1; j <= m; j ++ ){
			if (cal(x, y) > cal(i, j)){
				x = i;
				y = j;
			}
		}
	}
	cout << x << " " << y << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T;
	cin >> T;
	while (T -- )
		solve();
	return 0;
}
posted on 2022-06-15 21:16  Hamine  阅读(58)  评论(0编辑  收藏  举报