题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=2097

题解

显然二分一个 \(mid\) 表示每一块的直径长度的最大值,求最少需要多少连通块。

然后我们发现如果一个合法连通块的直径没有经过这个连通块的顶点,那么在顶点上加边时,这个连通块的直径就可以忽略了,因为无论如何都无法使得这个原来的直径边长了。因此只需要考虑从顶点向下的最长链就可以了。

于是我们记录一个 \(f[i]\) 表示以 \(i\) 为根的连通块的最长链的长度。然后贪心,从子树合并到根的时候,我们将所有的 \(f[son]\) 排序,然后找到最大满足相邻的两个合并起来小于等于 \(mid\) 的。后面的就全部需要割掉了。


代码如下,由于需要排序,时间复杂度 \(O(n\log n)\)。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 1e5 + 7; int n, m, cnt;
int tt[N], f[N]; struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); } inline void dfs(int x, const int &mid, int fa = 0) {
for fec(i, x, y) if (y != fa) dfs(y, mid, x);
tt[0] = 0, f[x] = 0;
for fec(i, x, y) if (y != fa) tt[++tt[0]] = f[y] + 1;
std::sort(tt + 1, tt + tt[0] + 1);
for (int i = tt[0]; i; --i)
if ((i == 1 && tt[i] <= mid) || tt[i] + tt[i - 1] <= mid) {
f[x] = tt[i];
break;
} else ++cnt;
} inline bool check(const int &mid) {
cnt = 0;
dfs(1, mid);
return cnt <= m;
} inline void work() {
int l = 0, r = n - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
printf("%d\n", l);
} inline void init() {
read(n), read(m);
for (int i = 1; i < n; ++i) {
int x, y;
read(x), read(y);
adde(x, y);
}
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

BZOJ2097 [Usaco2010 Dec]Exercise 奶牛健美操 贪心的更多相关文章

  1. BZOJ2097: [Usaco2010 Dec]Exercise 奶牛健美操 贪心+伪树dp+二分

    //论全局变量的杀伤力....QAQ#include<cstdio> #include<iostream> #include<cstdlib> #include&l ...

  2. [bzoj2097][Usaco2010 Dec]Exercise 奶牛健美操_贪心_树形dp_二分

    Exercise bzoj-2097 Usaco-2010 Dec 题目大意:题目链接 注释:略. 想法:题目描述生怕你不知道这题在考二分. 关键是怎么验证?我们想到贪心的删边. 这样的策略是显然正确 ...

  3. BZOJ2097: [Usaco2010 Dec]Exercise 奶牛健美操

    n<=100000的树,砍S<n条边,求砍完后S+1棵树的最大直径的最小值. 树的直径要小小哒,那考虑一棵子树的情况吧!一棵子树的直径,就是子树根节点各儿子的最大深度+次大深度.就下面这样 ...

  4. [Usaco2010 Dec]Exercise 奶牛健美操

    [Usaco2010 Dec]Exercise 奶牛健美操 题目 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连 ...

  5. BZOJ_2097_[Usaco2010 Dec]Exercise 奶牛健美操_二分答案+树形DP

    BZOJ_2097_[Usaco2010 Dec]Exercise 奶牛健美操_二分答案+树形DP Description Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的 ...

  6. 【bzoj2097】[Usaco2010 Dec]Exercise 奶牛健美操 二分+贪心

    题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径. ...

  7. BZOJ 2097: [Usaco2010 Dec]Exercise 奶牛健美操 二分 + 贪心 + 树上问题

    Code: #include<bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in",& ...

  8. BZOJ——T 2097: [Usaco2010 Dec]Exercise 奶牛健美操

    http://www.lydsy.com/JudgeOnline/problem.php?id=2097 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit:  ...

  9. bzoj 2097: [Usaco2010 Dec]Exercise 奶牛健美操【二分+树形dp】

    二分答案,然后dp判断是否合法 具体方法是设f[u]为u点到其子树中的最长链,每次把所有儿子的f值取出来排序,如果某两条能组合出大于mid的链就断掉f较大的一条 a是全局数组!!所以要先dfs完子树才 ...

随机推荐

  1. Win7 64位系统 注册 ocx控件

    32位系统注册ocx就不谈了.网上一搜一大把.下面说下win7 64位 旗舰版下如果注册ocx控件    1.首先复制 XXXX.OCX文件到“C:\Windows\SysWOW64”目录. (XXX ...

  2. ConcurrentModificationException异常

    介绍一个我今天在开发中遇到的异常:ConcurrentModificationException异常,当然它是一个非受检的异常,也就是运行时异常. 当我们在遍历集合对象的时候,不能够将集合删除.最佳实 ...

  3. ResultSet用法集锦 (转)

    转:http://soft-development.iteye.com/blog/1420323 结果集(ResultSet)是数据中查询结果返回的一种对象,可以说结果集是一个存储查询结果的对象,但是 ...

  4. JavaBean属性和成员变量的区别和联系

    JavaBeans是Java中一种特殊的类,可以将多个对象封装到一个对象(bean)中.特点是可序列化,提供无参构造器,提供getter方法和setter方法访问对象的属性.名称中的“Bean”是用于 ...

  5. 相同name,取最小的id的值,mysql根据相同字段 更新其它字段

    id name info1 a 1232 a 2353 a 1244 b 125 b 987相同name,取最小的id的值id name info1 a 1232 a 1233 a 1234 b 12 ...

  6. ST表——————一失足成千古恨系列2

    在此先祝自己这个系列写的越少越好qwq(保证不超过4篇(flag已立)) 考试原题:(绝壁是看完复联出的) 第一反应:线段树??不对,是st表.嗯,没错.哎,st表咋写来着??完了凉了. 结果:写暴搜 ...

  7. Oracle--索引视图序列等对象

    ---恢复内容开始--- 索引 与表类似,不仅需要在DD中保存索引的定义,还需要在表空间为它分配实际的存储空间. 将索引和对应的表分别存放在不同硬盘的不同表空间中能够提高查询的速度,因为Oracle能 ...

  8. Play with Chain 【HDU - 3487】【Splay+TLE讲解】

    题目链接 很好的一道题,用了三天多的时间,终于知道了我为什么T的原因,也知道了在Splay的同时该怎样子的节约时间,因为Splay本身就是大常数的O(N*logN),我们如果不在各种细节上节约时间,很 ...

  9. Adam Optimization Algorithm

    曾经多次看到别人说起,在选择Optimizer的时候默认就选Adam.这样的建议其实比较尴尬,如果有一点科学精神的人,其实就会想问为什么,并搞懂这一切,这也是我开这个Optimizer系列的原因之一. ...

  10. 有趣的linux指令

    1.cmatrix sudo apt-get update sudo apt-get install cmatrix 2.asciiquarium wget http://search.cpan.or ...