USACO20Feb Delegation P 【贪心】【二分答案】
跟Delegation G挺像的,还是贪心
二分答案套二分答案?
首先看到题目的求最小值最大,基本上可以确定二分答案,把最优问题变成可行问题
然后check的策略就是贪心,对于一个子树,如果他有奇数个子树,那么贪心的留一个最大长度的子树给祖先匹配,剩下的子树自己匹配,如果有偶数个子树,添加一个长度为0的子树即可
可以用再用一个二分答案确定留给祖先的子树,自己匹配部分贪心最小配最大即可
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#define gi get_int()
const int MAXN = 2e5;
int get_int()
{
int x = 0, y = 1;
char ch = getchar();
while (!isdigit(ch) && ch != '-')
ch = getchar();
if (ch == '-')
y = -1, ch = getchar();
while (isdigit(ch))
x = x * 10 + ch - '0', ch = getchar();
return x * y;
}
class Edge
{
public:
int next, to;
} edges[MAXN];
int head[MAXN], eNum;
void addEdge(int from, int to)
{
edges[eNum] = (Edge) {head[from], to};
head[from] = eNum++;
}
int mid;
int len[MAXN];
std::vector<int> num[MAXN];
int check(int now, int save, int nNum)
{
for (int i = 0, j = nNum - 1; i < j; i++, j--) {
if (i == save) i++;
if (j == save) j--;
if (num[now][i] + num[now][j] < mid) return false;
}
return true;
}
int dfs(int now = 0, int pre = -1)
{
num[now].clear();
for (int i = head[now]; i != -1; i = edges[i].next) {
int to = edges[i].to;
if (to == pre) continue;
if (dfs(to, now) == false)
return false;
num[now].push_back(len[to] + 1);
}
int cnt = num[now].size();
if ((pre != -1 && cnt % 2 == 0) || (pre == -1 && cnt % 2 != 0)) {
num[now].push_back(0);
cnt++;
}
std::sort(num[now].begin(), num[now].end());
if (pre == -1)
return check(now, -1, cnt);
if (check(now, 0, cnt) == false) return false;
int l = 0, r = cnt - 1, ans = 0;
while (l <= r) {
int midInside = (l + r) / 2;
if (check(now, midInside, cnt) == true) {
ans = num[now][midInside];
l = midInside + 1;
} else {
r = midInside - 1;
}
}
len[now] = ans;
return true;
}
int main()
{
freopen("code.in", "r", stdin);
freopen("code.out", "w", stdout);
int n = gi;
memset(head, -1, sizeof(head));
for (int i = 1; i < n; i++) {
int from = gi - 1, to = gi - 1;
addEdge(from, to);
addEdge(to, from);
}
int l = 0, r = 1e8, ans = -1;
while (l <= r) {
mid = (l + r) / 2;
if (dfs() == true) {
l = mid + 1;
ans = mid;
} else {
r = mid - 1;
}
}
std::cout << ans;
return 0;
}

浙公网安备 33010602011771号