点此看题面

大致题意: 给你一棵树,询问对于每个点需要改变多少条边来使得它成为树中到所有点距离和最小的点。

一些初始化及想法

这是一道思博题

首先我们要知道一个结论:对于这棵树的重心,它的答案必定为\(0\)。

然后对于非重心的点该怎么办呢?

我们考虑把重心作为根,并统计出每个子节点的\(Size\)。

接下来我们可以发现,如果割掉根节点的若干棵子树,且这些子树\(Size\)和\(\ge\frac n2\),那么肯定就可以构造出一种合法的方案使得任意节点符合条件。

由于要割的次数最少,因此我们将根节点的子节点按\(Size\)从大到小排序,然后取尽量少的节点使得\(Size\)和\(\ge\frac n2\),并记录所需节点数为\(p\)。

答案的取值

对于除重心外的每个点,其答案只可能为\(p\)或者\(p-1\)。

什么时候能够取\(p-1\)呢?

假设一个点\(x\)位于根节点的子节点排序后的第\(i\)个子节点的子树内。

对于\(i\le p\),我们割去除\(i\)外第\(1\sim p\)个点到根节点的连边。如果这些被割去的子树的\(Size\)和加上\(Size_x\ge\frac n2\),那么我们就不需要再割一条新边了。

而对于\(i>p\)的情况也是类似的,只不过一开始割去的是第\(1\sim p-1\)个点到根节点的连边。

按照这样的方式,我们就可以求出答案了。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define INF 1e9
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
#define max(x,y) ((x)>(y)?(x):(y))
#define Gmax(x,y) (x<(y)&&(x=(y)))
using namespace std;
int n,p,rt,cnt,ee,s[N+5],lnk[N+5],Sz[N+5],Mx[N+5],ans[N+5];struct edge {int to,nxt;}e[N<<1];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
I void GetRt(CI x,CI lst=0)//求重心
{
for(RI i=(Sz[x]=1,Mx[x]=0,lnk[x]);i;i=e[i].nxt) e[i].to^lst&&
(GetRt(e[i].to,x),Sz[x]+=Sz[e[i].to],Gmax(Mx[x],Sz[e[i].to]));
Gmax(Mx[x],n-Sz[x]),Mx[x]<Mx[rt]&&(rt=x);
}
I void Init(CI x,CI lst=0)//初始化Size
{
for(RI i=(Sz[x]=1,lnk[x]);i;i=e[i].nxt)
e[i].to^lst&&(Init(e[i].to,x),Sz[x]+=Sz[e[i].to]);
}
I void GetAns(CI x,CI lst,CI v)//求解答案
{
ans[x]=p,(Sz[x]+v<<1)>=n&&--ans[x];//判断答案是否可以减1
for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(GetAns(e[i].to,x,v),0);//遍历子树
}
I bool cmp(CI x,CI y) {return Sz[x]>Sz[y];}//按Size排序
int main()
{
RI i,x,y;for(F.read(n),i=1;i^n;++i) F.read(x,y),add(x,y),add(y,x);//读入+建边
for(Mx[rt=0]=INF,GetRt(1),Init(rt),cnt=0,i=lnk[rt];i;i=e[i].nxt) s[++cnt]=e[i].to;//找到重心,将重心儿子存下来用于排序
for(sort(s+1,s+cnt+1,cmp),x=0,i=1;i<=cnt&&(x<<1)<n;++i) x+=Sz[s[i]];p=i-1;//排序,然后求出p
for(i=1;i<=cnt;++i) GetAns(s[i],rt,x-max(Sz[s[i]],Sz[s[p]]));//枚举子节点处理答案
for(i=1;i<=n;++i) F.writeln(ans[i]);return F.clear(),0;//输出
}

【LOJ6042】「雅礼集训 2017 Day7」跳蚤王国的宰相(思博题)的更多相关文章

  1. 「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心)

    题面 来源 「 雅 礼 集 训 2017 D a y 7 」 跳 蚤 王 国 的 宰 相   传 统 2000   m s 1024   M i B {\tt「雅礼集训 2017 Day7」跳蚤王国的 ...

  2. LOJ #6042. 「雅礼集训 2017 Day7」跳蚤王国的宰相

    我可以大喊一声这就是个思博题吗? 首先如果你能快速把握题目的意思后,就会发现题目就是让你求出每个点要成为树的重心至少要嫁接多少边 先说一个显然的结论,重心的答案为\(0\)(废话) 然后我们考虑贪心处 ...

  3. 【思维题 细节】loj#6042. 「雅礼集训 2017 Day7」跳蚤王国的宰相

    挂于±1的细节…… 题目描述 跳蚤王国爆发了一场动乱,国王在镇压动乱的同时,需要在跳蚤国地方钦定一个人来做宰相. 由于当时形势的复杂性,很多跳蚤都并不想去做一个傀儡宰相,带着宰相的帽子,最后还冒着被打 ...

  4. 「雅礼集训 2017 Day7」事情的相似度

    「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...

  5. 【LOJ 6041】「雅礼集训 2017 Day7」事情的相似度

    Description 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的 ...

  6. 【刷题】LOJ 6041 「雅礼集训 2017 Day7」事情的相似度

    题目描述 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的有相同的事情发 ...

  7. LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度

    我可以大喊一声这就是个套路题吗? 首先看到LCP问题,那么套路的想到SAM(SA的做法也有) LCP的长度是它们在parent树上的LCA(众所周知),所以我们考虑同时统计多个点之间的LCA对 树上问 ...

  8. loj#6041. 「雅礼集训 2017 Day7」事情的相似度(SAM set启发式合并 二维数点)

    题意 题目链接 Sol 只会后缀数组+暴躁莫队套set\(n \sqrt{n} \log n\)但绝对跑不过去. 正解是SAM + set启发式合并 + 二维数点/ SAM + LCT 但是我只会第一 ...

  9. LOJ #6043. 「雅礼集训 2017 Day7」蛐蛐国的修墙方案

    我可以大喊一声这就是个SB题吗? 首先讲一句如果你像神仙CXR一样精通搜索你就可以得到\(80pts\)(无Subtask)的好成绩 我们考虑挖掘一下题目的性质,首先发现这是一个置换,那么我们发现这的 ...

随机推荐

  1. oracle 笔记---(五)__内存管理

    ###查看连接池的信息 select connection_pool,status,maxsize from dba_cpool_info            

  2. DB Intro - MongoDB Basic

    mongoDB basic from:http://www.tutorialspoint.com/mongodb prject:https://github.com/chenxing12/l4mong ...

  3. Unity 修改windows窗口的标题

    修改windows窗口的标题名称,就是修改下图的东西: 第一种: using UnityEngine; using System; using System.Runtime.InteropServic ...

  4. UNIX文件mode_t详解 ... S_IRUSR

    打开文件.新建文件和关闭文件操作 打开文件操作使用系统调用函数open(),该函数的作用是建立一个文件描述符,其他的函数可以通过文件描述符对指定文件进行读取与写入的操作.打开文件的一般形式是: ope ...

  5. gradle cache目录(.gradle)剖析

    https://zhuanlan.zhihu.com/p/26473930 gradle下载后会对文件路径进行修饰,本文给出反向解析,把文件路径修改为原始路径的办法. 之所以研究这个,本来的目的是为了 ...

  6. vim源码编译启用python

    坑:只指定with-python-config-dir没有指定enable-pythoninterp是没有用的 ./configure --enable-pythoninterp --with-pyt ...

  7. embedded tomcat运行java web,Unable to compile class for JSP

    环境 eclipse:4.5.2 jre:1.8 java project compiler:1.8 embedded tomcat:7.0.32 可以正常启动,但是访问时,会报错. HTTP Sta ...

  8. js 获取时间相关

    $(document).ready(function () {            var date = new Date();            var sb = "";  ...

  9. ubuntu系统没有声音解决方法

    好像装了个放视频的软件,就没有声音了.后面网上搜到了一个简单粗暴的办法,效果很明显,改变权限后直接就有声音了. -------------------------------------------- ...

  10. onload与ready差异

    window.onload: 等所有资源加载完document.ready: DOM树构建完资源还没加载完 应该使用ready保证用户体验.否则当网站有很多图片资源时要很长时间才能加载完这段时间内Js ...