联盟

题目描述

\(\text{G}\) 国周边的 \(n\) 个小国家构成一个联盟以抵御 \(\text{G}\) 国入侵, 为互相支援,他们建立了\(n−1\) 条双向通路, 使得任意两个国家可以经过通路相互到达.

当一个国家受到攻击时, 所有其它国家都会沿着最短路径前往这个国家进行支援,经过每条通路所需的时间均为\(1\). 定义一个国家的危险程度为所有国家全部赶到需要的最短时间, 联盟的危险程度为所有国家的危险程度的最大值.

为了降低危险程度, 联盟决定断开一条通路并任意连接一条通路, 使得危险程度尽可能小, 并要求改建完成之后任意两个国家可以经过通路互相到达.

他们决定让你来设计方案, 你需要告知在最优方案中可能断开哪些边,并给出任意一组最优方案.

输入输出格式

输入格式

第一行一个正整数\(n\).

接下来 \(n-1\) 行每行两个正整数, 表示一条\(u_i\), \(v_i\) 之间的边.

输出格式

输出第一行一个整数表示最小危险程度.

第二行一个整数 \(k\), 表示可能被断开的边的数量, 接下来 \(k\) 个数, 表示

可能断开的边的编号, 按升序输出.

接下来一行四个正整数表示一组最优方案, 分别表示断开和新建的边的端点, 只需给出任意一组合法的方案即可.

提示

对于\(20\%\)的数据,\(n\le 30\).

对于\(40\%\)的数据,\(n\le 300\).

对于\(60\%\)的数据,\(n\le 3000\).

对于\(100\%\)的数据,\(n\le 300000\).

如果你的答案仅第一行正确, 你可以获得 \(25\%\) 的分数,

如果你的答案仅前两行正确, 你可以获得 \(50\%\) 的分数,

为保证得到部分分请确保提交程序的输出格式符合题目要求.


其实思维没什么难度。

枚举断边,处理出两颗分开的树的直径,求一下新的直径就可以了

已知两棵树的直径分别为\(a,b\),用一条边连接这两颗树得到的最小直径是\(max(a,b,\lceil \frac{a}{2} \rceil +\lceil \frac{b}{2} \rceil +1)\),就是连接这个直径中间的点

细节非常多,写起来很恶心,可以练练代码能力

考场上硬是没调出来爆0了。。。


Code:

#include <cstdio>
#include <algorithm>
#include <vector>
const int N=3e5+10;
int Next[N<<1],to[N<<1],head[N],cnt;
int max(int x,int y){return x>y?x:y;}
void add(int u,int v,int eid)
{
to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int n,dis[N],dp[N],s[N],tot0,ans=0x7fffffff;
void dfs1(int now,int fa)
{
int mx1=0,mx2=0,child=0;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa) continue;
child++;
dfs1(v,now);
dp[now]=max(dp[v],dp[now]);
dis[now]=max(dis[now],dis[v]+1);
if(mx1<=dis[v]) mx2=mx1,mx1=dis[v];
else if(mx2<dis[v]) mx2=dis[v];
}
if(child>1) dp[now]=max(dp[now],mx1+mx2+2);
else dp[now]=max(dp[now],mx1+mx2+child);
}
void dfs2(int now,int fa,int len1,int len2,int num)
{
int mi=max(max(dp[now],len1),(dp[now]+1)/2+(len1+1)/2+1),child=0;
if(mi<ans) tot0=0,s[++tot0]=num,ans=mi;
else if(mi==ans) s[++tot0]=num;
int max1=0,dmax1=0,fmax1=0,max2=0,dmax2=0;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa) continue;
if(dis[v]>=max1) fmax1=dmax1,dmax1=max1,max1=dis[v];
else if(dis[v]>=dmax1) fmax1=dmax1,dmax1=dis[v];
else if(dis[v]>fmax1) fmax1=dis[v];
if(dp[v]>=max2) dmax2=max2,max2=dp[v];
else if(dp[v]>dmax2) dmax2=dp[v];
++child;
}
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa) continue;
int mxx0,mxx1;
if(max1==dis[v]) mxx0=dmax1,mxx1=fmax1;
else if(dmax1==dis[v]) mxx0=max1,mxx1=fmax1;
else mxx0=max1,mxx1=dmax1;//儿子链的最大值
int mxx2=(max2==dp[v]?dmax2:max2);//其他儿子的直径
int lenp=max((len2+(mxx0+1)*(child>1)),(mxx0+mxx1+2)*(child>2));//三条链的最值
int le1=max(len1,max(mxx2,lenp)),le2=max(len2+1,(mxx0+2)*(child>1));
dfs2(v,now,le1,le2,i+1>>1);
}
}
struct edge
{
int u,v;
}e[N];
int s0[2][N],mxlen,ll,rr,pre[N];
void dfs3(int now,int fa,int len)
{
if(len>mxlen) mxlen=len,ll=now;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa||(i+1>>1)==s[1]) continue;
dfs3(v,now,len+1);
}
}
void dfs4(int now,int fa,int len)
{
if(len>mxlen) mxlen=len,rr=now;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa||(i+1>>1)==s[1]) continue;
pre[v]=now;
dfs4(v,now,len+1);
}
}
void getd(int st,int ty)
{
mxlen=0;
dfs3(st,0,1);
mxlen=0;
dfs4(ll,0,1);
int now=rr;
while(now) s0[ty][++s0[ty][0]]=now,now=pre[now];
}
void work3()
{
int lu=e[s[1]].u,lv=e[s[1]].v;
getd(lu,0),getd(lv,1);
int u=s0[0][s0[0][0]+1>>1],v=s0[1][s0[1][0]+1>>1];
printf("%d %d %d %d\n",lu,lv,u,v);
}
int main()
{
scanf("%d",&n);
for(int u,v,i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
e[i]={u,v};
add(u,v,i),add(v,u,i);
}
dfs1(1,0);
dfs2(1,0,0,0,0);
printf("%d\n",ans);
std::sort(s+1,s+1+tot0);
printf("%d ",tot0);
for(int i=1;i<=tot0;i++) printf("%d ",s[i]);
printf("\n");
work3();
return 0;
}

2018.10.2

雅礼集训 Day2 T3 联盟 解题报告的更多相关文章

  1. 雅礼集训 Day3 T3 w 解题报告

    w 题目背景 \(\frac 14\)遇到了一道水题,双完全不会做,于是去请教小\(\text{D}\).小\(\text{D}\)看了\(0.607^2\)眼就切掉了这题,嘲讽了\(\frac 14 ...

  2. 雅礼集训 Day1 T3 画作 解题报告

    画作 题目描述 小\(\mathrm{G}\)的喜欢作画,尤其喜欢仅使用黑白两色作画. 画作可以抽象成一个\(r\times c\)大小的\(01\)矩阵.现在小\(\mathrm{G}\)构思好了他 ...

  3. 雅礼集训 Day5 T3 题 解题报告

    题 题目背景 由于出题人赶时间所以没办法编故事来作为背景. 题目描述 一开始有\(n\)个苹果,\(m\)个人依次来吃苹果,第\(i\)个人会尝试吃\(u_i\)或\(v_i\)号苹果,具体来说分三种 ...

  4. 「雅礼集训 2017 Day1」 解题报告

    「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...

  5. 雅礼集训 Day7 T1 Equation 解题报告

    Reverse 题目背景 小\(\text{G}\)有一个长度为\(n\)的\(01\)串\(T\),其中只有\(T_S=1\),其余位置都是\(0\).现在小\(\text{G}\)可以进行若干次以 ...

  6. 雅礼集训 Day6 T2 Equation 解题报告

    Equation 题目描述 有一棵\(n\)个点的以\(1\)为根的树,以及\(n\)个整数变量\(x_i\).树上\(i\)的父亲是\(f_i\),每条边\((i,f_i)\)有一个权值\(w_i\ ...

  7. 雅礼集训 Day6 T1 Merchant 解题报告

    Merchant 题目描述 有\(n\)个物品,第\(i\)个物品有两个属性\(k_i,b_i\),表示它在时刻\(x\)的价值为\(k_i\times x+b_i\). 当前处于时刻\(0\),你可 ...

  8. 雅礼集训 Day3 T2 u 解题报告

    u 题目背景 \(\frac 14\) 遇到了一道水题,完全不会做,于是去请教小\(\text{D}\).小\(\text{D}\)看了一眼就切掉了这题,嘲讽了\(\frac 14\)一番就离开了. ...

  9. 雅礼集训 Day3 T2 v 解题报告

    v 题目背景 \(\frac 14\)遇到了一道水题,又完全不会做,于是去请教小\(\text{D}\).小\(\text{D}\)看了\(0.607\)眼就切掉了这题,嘲讽了\(\frac 14\) ...

随机推荐

  1. motto - Express 4.x Request对象获得参数方法

    本文搜索关键字:motto express node js nodejs javascript request body request.body 1. req.param() 该方法获得参数最为方便 ...

  2. GNU汇编 伪指令

    伪指令 本身并没有所对应的机器码 它只是在编译的时候起作用,或者转换为其他的实际指令来运行 global ascii byte word data equ align @ 下面的例子是在数据段存放数据 ...

  3. 用PHP关于Jquery表单插件ajaxForm里success不返回问题

    简单说一下吧,在用ajaxForm的时候,sucess突然之间不返回了,直接转到error里面去, 网页代码 ................. $('#add-type').ajaxForm({ d ...

  4. Docker使用入门

    docker images 查看本地镜像 docker ps -a  查询容器 docker ps -l  查询最近使用容器 docker rm CONTAINER_ID 删除容器 docker rm ...

  5. 一个比较良好的flask项目结构

    一个比较良好的flask项目结构 project/ app/                    # 整个程序的包目录 static/                 # 静态资源文件 js/    ...

  6. 笔记-reactor pattern

    笔记-reactor pattern 1.      reactor模式 1.1.    什么是reactor模式 The reactor design pattern is an event han ...

  7. 理解线程3 c语言示例线程基本操作

    Table of Contents 1. 基本线程的动作 1.1. 设置线程属性 1.1.1. 设置脱离状态 1.1.2. 设置调度属性 1.2. 取消线程 1.3. 主线程创建多个线程示例 2. 了 ...

  8. 4x4矩阵键盘 扫描程序

    一:不排除第四位异常处理 uchar JuzhenkeyScan() { // P3=0xfe; // temp=P3; // while(temp!=0xfe) // { // temp=P3; / ...

  9. android gradle 给所有的buildFlavor 的versionName 增加一个后缀

    build里面有很多的productFlavors,我想要给所有的productFlavors 的versionName增加一个后缀比如:_20180323 怎么做?注意是所有的productFlav ...

  10. Kafka安装和常用操作命令

    Kafka安装: 下载kafka_2.10-0.8.2.1 1.关闭防火墙 2.修改配置文件  server.properties broker.id=1log.dirs= /usr/kafka_2. ...