
【2020.11.30提高组模拟】剪辣椒(chilli)
每一餐不可以太辣,所以你会寻找一个剪绳子的方法,使得最大组成部分和最小组成部分的辣椒数量差最小。计算出这个最小差值。
发布日期:2021-05-06 15:40:52
浏览次数:46
分类:精选文章
本文共 2265 字,大约阅读时间需要 7 分钟。
剪辣椒(chilli)
题目描述
在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己。
你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树。 你决定分三餐吃完这些辣椒,因此需要剪断其中两根绳子,从而得到三个组成部分,每一餐吃一个组成部分即可。
输入格式
输入文件名为chilli.in。
第一行一个整数n,表示辣椒的数量。辣椒从1到n进行编号。 下面n-1行每一行包含两个整数x和y(1≤x,y≤n),表示辣椒x和辣椒y直接用一根绳子相连。输出格式
输出文件名为chilli.out。
输出最小差值。题解
题目大意:删掉一棵树上的两条边使得形成的三棵树里 s i z e size size最大的减 s i z e size size最小的差值最小,问最小差值
先求出以每个点为根的子树的大小 s i z e i size_i sizei(假定1为整棵树的根) 然后枚举每个点(用 d f s dfs dfs,在到每个点的时候就计算贡献,即删除当前点与父亲的边,做完之后把 n − s i z e x n-size_x n−sizex加到 s e t set set,结束后从 s e t set set中移除),删掉它与它父亲的边,这时将整棵树分成两部分: s i z e x size_x sizex和 n − s i z e x n-size_x n−sizex,然后在 n − s i z e x n-size_x n−sizex里找到 ⌈ n − s i z e x 2 ⌉ \lceil\dfrac{n-size_x}{2}\rceil ⌈2n−sizex⌉的前驱后继,这里可以用 s e t set set里的 l o w e r _ b o u n d lower\_bound lower_bound(不会用 s e t set set可以自行搜索,这里推荐一篇写的比较好的文章)。关于另一条边,有两种情况,一种是祖先边,上面已经计算,另一种是非祖先边,可以再用一个 d f s dfs dfs,但与上面有所不同,这里是删除当前点与儿子的边,然后结束后加入 s i z e x size_x sizexCode
#include#include #include #include #define inf 2147483600using namespace std;struct node{ int next,to,head;}a[400001];int n,x,y,ans,tot,size[200001];multiset q;multiset ::iterator it;void add(int x,int y){ a[++tot].to=y; a[tot].next=a[x].head; a[x].head=tot;}void getsize(int now,int fa){ size[now]=1; for (int i=a[now].head;i;i=a[i].next) { if (a[i].to==fa) continue; getsize(a[i].to,now); size[now]+=size[a[i].to]; }}int getans(int x,int y,int z) { return max(x,max(y,z))-min(x,min(y,z));}void calc(int x){ int p=n-size[x]; it=q.lower_bound((p+1)>>1); if (it!=q.end()) ans=min(ans,getans(size[x],p-*it,*it)); if (it!=q.begin()) it--,ans=min(ans,getans(size[x],p-*it,*it)); it=q.lower_bound(max(size[x],p-size[x])); if (it!=q.end()) ans=min(ans,*it*2-p);}void dfs1(int now,int fa){ calc(now); q.insert(n-size[now]); for (int i=a[now].head;i;i=a[i].next) { if (a[i].to==fa) continue; dfs1(a[i].to,now); } q.erase(n-size[now]);}void dfs2(int now,int fa){ for (int i=a[now].head;i;i=a[i].next) { if (a[i].to==fa) continue; calc(a[i].to); dfs2(a[i].to,now); } q.insert(size[now]);}int main(){ freopen("chilli.in","r",stdin); freopen("chilli.out","w",stdout); scanf("%d",&n); for (int i=1;i
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2025年03月26日 17时03分58秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
老Python总结的字典相关知识
2021-05-09
jQuery的事件绑定与触发 - 学习笔记
2021-05-09
Linux上TCP的几个内核参数调优
2021-05-09
记一次讲故事机器人的开发-我有故事,让机器人来读
2021-05-09
seo 回忆录百度基本概念(一)
2021-05-09
netcore中使用session
2021-05-09
Android 开发学习进程0.25 自定义控件
2021-05-09
多媒体文件格式全解说(下)--图片
2021-05-09
淘宝WAP版小BUG分析
2021-05-09
asp.net打印网页后自动关闭网页【无需插件】
2021-05-09
【Maven】POM基本概念
2021-05-09
【Java思考】Java 中的实参与形参之间的传递到底是值传递还是引用传递呢?
2021-05-09
【设计模式】单例模式
2021-05-09
远程触发Jenkins的Pipeline任务的并发问题处理
2021-05-09
Web应用程序并发问题处理的一点小经验
2021-05-09
entity framework core在独立类库下执行迁移操作
2021-05-09
Asp.Net Core 2.1+的视图缓存(响应缓存)
2021-05-09
【wp】HWS计划2021硬件安全冬令营线上选拔赛
2021-05-09
Ef+T4模板实现代码快速生成器
2021-05-09