比赛链接:
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;
}