构造题 Codeforces2133E
https://codeforces.com/problemset/problem/2133/E
题解
第一个操作没那么好理解,因为询问了某个位置之后下一步逃犯还不能走那个位置。所以先用几个具体实例来理解这个追逃游戏。
在链上可以惊喜地发现,这个特性可以让我们在链长次询问得到逃犯的位置。而且联想一下,发现我们必须要用操作 1 问出逃犯的位置,也就是询问操作至少都要有 n 次。
接下来思考操作 2,发现操作 2 肯定是放在操作 1 前最优,肯定是先切断他能走的路,再用询问逼迫他。
然后问题就变成求,先去掉 n/4 个点,剩下一堆链的方案。
直接使用题解的方法 dp:
将树以节点 1 为根。定义绿色节点为其子树中某条路径的端点,黄色节点为其子树中某条路径的中间节点,黑色节点为我们执行操作 2 的节点。然后对每个节点:
如果它有三个或更多绿色子节点,或者有任何黄色子节点,则将其染为黑色。
否则,如果它恰好有两个绿色子节点(且其他子节点都是黑色),则将其染为黄色。
否则,将其染为绿色。
代码,直接抄题解的,写的还不错:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) x.begin(), x.end()
#define vecin(name, len) vector<int> name(len); for (auto &_ : name) cin >> _;
#define vecout(v) for (auto _ : v) cout << _ << " "; cout << endl;
const int MAXN = 200005;
vector<int> adj[MAXN];
int colour[MAXN];
vector<pair<int, int>> ans;
vector<int> leaves;
bool vis[MAXN];
void dfs(int node, int parent) {
vector<int> children;
for (auto a : adj[node])
if (a != parent) {
dfs(a, node);
children.push_back(a);
}
int num_1_children = 0;
bool any_2_children = false;
for (auto child : children) {
if (colour[child] == 1)
num_1_children ++;
else if (colour[child] == 2)
any_2_children = true;
}
if (any_2_children || num_1_children >= 3) {
colour[node] = 0;
ans.push_back({2, node + 1});
ans.push_back({1, node + 1});
} else if (num_1_children == 2) {
colour[node] = 2;
} else {
colour[node] = 1;
if (num_1_children == 0)
leaves.push_back(node);
}
}
void dfs2(int node) {
vis[node] = true;
ans.push_back({1, node + 1});
for (auto a : adj[node])
if (colour[a] != 0 && !vis[a])
dfs2(a);
}
void solve() {
int n; cin >> n;
for (int i = 0; i < n; i ++)
adj[i].clear(), vis[i] = false;
for (int i = 0; i < n - 1; i ++) {
int a, b; cin >> a >> b;
a --; b --;
adj[a].push_back(b);
adj[b].push_back(a);
}
ans.clear();
leaves.clear();
dfs(0, -1);
for (auto a : leaves)
if (!vis[a])
dfs2(a);
cout << ans.size() << endl;
for (auto a : ans)
cout << a.first << " " << a.second << endl;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int tt = 1;
cin >> tt;
while (tt--) solve();
return 0;
}

浙公网安备 33010602011771号