1452G Game On Tree(拓扑+贪心)
Educational Codeforces Round 98 (Rated for Div. 2)
G. Game On Tree
题面:Game On Tree
题意:Alice 和 Bob 在一颗有 n n n 个节点的树上进行博弈,一开始 Bob 在树上有 k k k 个士兵,分别在 a i a_i ai 节点上(不重复),而 Alice 在这颗树上只有一个士兵,他需要躲避 Bob 士兵的追捕,当 Alice 的士兵被 Bob 的士兵抓到,即位于同一节点时游戏结束。
每个回合中,Alice 先选择让自己的士兵往邻点移动一步,或者停在原地,然后 Bob 分别对自己的每个士兵选择往邻点移动一步,或者停在原地。
Alice 想要自己的士兵尽可能晚得被抓到,Bob 想要尽可能早得抓到 Alice 的士兵,两人都足够聪明。问当 Alice 将自己的士兵放置于点 1 , 2 , 3... , n 1,2,3...,n 1,2,3...,n 时被抓住的最晚时间是多少。
范围: 2 ≤ n ≤ 2 ∗ 1 0 5 , 1 ≤ k ≤ n − 1 , 1 ≤ a i ≤ n 2 \le n \le 2*10^5,~1 \le k \le n - 1,~1 \le a_i \le n 2≤n≤2∗105, 1≤k≤n−1, 1≤ai≤n。
分析:首先如果要判断一个点从逃往哪个点可以延长自己被抓到的时间,就先需要求出每个点 u u u 距离自己最近的 Bob 士兵的距离 d i s t [ u ] dist[u] dist[u],这个可以通过拓扑排序进行预处理出来。
每个点 u u u 都想要前往 d i s t [ v ] > d i s t [ u ] dist[v] > dist[u] dist[v]>dist[u] 的邻点 v v v 中,显然对于最大的 d i s t [ u ] dist[u] dist[u] 是没有办法变得更大,因此我们可以按照 d i s t dist dist 从大到小进行处理,从该点 u u u 出发找到所有可以到达 u u u 的所有点 v v v(需要保证中途不被抓到),去更新这些点的答案。
另外在上述处理过程中可能出现的问题是某些点会被重复遍历很多次,我们利用一个数组 h h h, h [ u ] h[u] h[u] 表示当前利用点 u u u 来更新答案时距离最近 Bob 士兵的距离,根据贪心的思想,在处理点 u u u 时只有当眼下距离最近 Bob 士兵的距离 d > h [ u ] d > h[u] d>h[u] 时,才有可能通过点 u u u 得到更优解。
Code:
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
const int MAXN = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);
int n, k;
int dist[MAXN], ans[MAXN], h[MAXN];
vector<int> E[MAXN], P[MAXN];
queue<int> que;
signed main()
{
memset(dist, -1, sizeof(dist));
n = read();
for (int i = 0; i < n - 1; i++)
{
int u, v;
u = read(), v = read();
E[u].push_back(v);
E[v].push_back(u);
}
k = read();
for (int i = 0; i < k; i++)
{
int x = read();
dist[x] = 0;
que.push(x);
}
int maxDist = 0;
while (!que.empty())
{
int u = que.front();
que.pop();
for (auto v : E[u])
{
if (dist[v] >= 0) continue;
dist[v] = dist[u] + 1;
que.push(v);
}
P[dist[u]].push_back(u);
maxDist = max(maxDist, dist[u]);
}
queue<pair<int, int>> que_pair;
for (int i = maxDist; i > 0; i--)
{
for (auto u : P[i])
{
if (h[u] < dist[u])
{
if (!ans[u]) ans[u] = i;
h[u] = dist[u];
que_pair.push({dist[u], u});
}
}
while (!que_pair.empty())
{
int d = que_pair.front().first;
int u = que_pair.front().second;
que_pair.pop();
if (--d == 0) continue;
for (auto v : E[u])
{
int temp = min(d, dist[v]);
if (h[v] < temp)
{
if (!ans[v]) ans[v] = i;
h[v] = temp;
que_pair.push({temp, v});
}
}
}
}
for (int i = 1; i <= n; i++)
{
if (i > 1) cout << " ";
cout << ans[i];
}
cout << endl;
return 0;
}
【END】感谢观看