$ \color{#0066ff}{ 题目描述 }$

给定一棵无根树,边权都是1,请去掉一条边并加上一条新边,定义直径为最远的两个点的距离,请输出所有可能的新树的直径的最小值和最大值

\(\color{#0066ff}{输入格式}\)

第一行包含一个正整数n(3<=n<=500000),表示这棵树的点数。接下来n-1行,每行包含两个正整数u,v(1<=u,v<=n),表示u与v之间有一条边。

\(\color{#0066ff}{输出格式}\)

第一行输出五个正整数k,x1,y1,x2,y2,其中k表示新树直径的最小值,x1,y1表示这种情况下要去掉的边的两端点,x2,y2表示这种情况下要加上的边的两端点。第二行输出五个正整数k,x1,y1,x2,y2,其中k表示新树直径的最大值,x1,y1表示这种情况下要去掉的边的两端点,x2,y2表示这种情况下要加上的边的两端点。若有多组最优解,输出任意一组。

\(\color{#0066ff}{输入样例}\)

6
1 2
2 3
2 4
4 5
6 5

\(\color{#0066ff}{输出样例}\)

3 4 2 2 5
5 2 1 1 6

\(\color{#0066ff}{数据范围与提示}\)

none

\(\color{#0066ff}{题解}\)

最长的情况,肯定是两个最长链拼一起,最短,就是两个最长链的中点相连

跑树形DP处理出每个点子树内的最长链和子树外的最长链,更新答案

最后两遍bfs找到端点即可

#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int inf = 0x7fffffff;
const int maxn = 1e6 + 10;
int f[maxn], g[maxn], up[maxn], dn[maxn][3], good[maxn][2], dep[maxn], F[maxn];
// 子树最长链,子树外最长链,以其为端点的最长链,次长链,次次长链(上下),子树f的最优,次优值,父亲
int n, minx, miny, maxx, maxy;
int min = inf, max;
struct node {
int to;
node *nxt;
node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {}
}*head[maxn];
std::queue<int> q;
bool vis[maxn];
void add(int from, int to) {
head[from] = new node(to, head[from]);
}
void dfs(int x, int fa) {
F[x] = fa;
dep[x] = dep[fa] + 1;
for(node *i = head[x]; i; i = i->nxt) {
if(i->to == fa) continue;
dfs(i->to, x);
f[x] = std::max(f[x], f[i->to]);
int now = dn[i->to][0] + 1;
if(now > dn[x][0]) { //向下的最长,次长,次次长链
dn[x][2] = dn[x][1];
dn[x][1] = dn[x][0];
dn[x][0] = now;
}
else if(now > dn[x][1]) {
dn[x][2] = dn[x][1];
dn[x][1] = now;
}
else if(now > dn[x][2]) dn[x][2] = now;
now = f[i->to];
if(now > good[x][0]) { //更新子树最优f
good[x][1] = good[x][0];
good[x][0] = now;
}
else if(now > good[x][1]) good[x][1] = now;
}
f[x] = std::max(f[x], dn[x][0] + dn[x][1]); //两条链更新f
}
void dfss(int x, int fa) {
if(x != 1) { //更新答案
if(max < f[x] + g[x] + 1) {
max = f[x] + g[x] + 1;
maxx = fa, maxy = x;
}
int upd = std::max(std::max(f[x], g[x]), ((f[x] + 1) >> 1) + ((g[x] + 1) >> 1) + 1);
if(min > upd) {
min = upd;
minx = fa, miny = x;
}
}
for(node *i = head[x]; i; i = i->nxt) {
if(i->to == fa) continue;
up[i->to] = std::max(up[i->to], up[x] + 1); //向上的最长链
g[i->to] = std::max(g[i->to], g[x]);
int now = dn[i->to][0] + 1;
if(now == dn[x][0]) { //讨论
g[i->to] = std::max(g[i->to], std::max(dn[x][1] + dn[x][2], up[x] + dn[x][1]));
up[i->to] = std::max(up[i->to], dn[x][1] + 1);
}
else if(now == dn[x][1]) {
g[i->to] = std::max(g[i->to], std::max(dn[x][0] + dn[x][2], up[x] + dn[x][0]));
up[i->to] = std::max(up[i->to], dn[x][0] + 1);
}
else {
g[i->to] = std::max(g[i->to], std::max(dn[x][0] + dn[x][1], up[x] + dn[x][0]));
up[i->to] = std::max(up[i->to], dn[x][0] + 1);
}
now = f[i->to];
if(now == good[x][0]) g[i->to] = std::max(g[i->to], good[x][1]);
else g[i->to] = std::max(g[i->to], good[x][0]);
dfss(i->to, x);
}
}
int getmid(int x, int y, int len) { //找中点
int now = len;
if(dep[x] < dep[y]) x ^= y ^= x ^= y;
while(now != (len + 1) >> 1) x = F[x], now--;
return x;
}
int bfsmin(int s) {
for(int i = 1; i <= n; i++) vis[i] = false;
vis[s] = true;
q.push(s);
while(!q.empty()) {
int tp = q.front(); q.pop();
s = tp;
for(node *i = head[tp]; i; i = i->nxt) {
if(vis[i->to]) continue;
if(tp == minx && i->to == miny) continue;
if(tp == miny && i->to == minx) continue;
q.push(i->to);
vis[i->to] = true;
}
}
return s;
}
int bfsmax(int s) {
for(int i = 1; i <= n; i++) vis[i] = false;
vis[s] = true;
q.push(s);
while(!q.empty()) {
int tp = q.front(); q.pop();
s = tp;
for(node *i = head[tp]; i; i = i->nxt) {
if(vis[i->to]) continue;
if(tp == maxx && i->to == maxy) continue;
if(tp == maxy && i->to == maxx) continue;
q.push(i->to);
vis[i->to] = true;
}
}
return s;
}
void predoit() {
dfs(1, 0), dfss(1, 0);
}
void getmin() {
printf("%d %d %d ", min, minx, miny);
int x = bfsmin(minx), y = bfsmin(x);
int s = bfsmin(miny), t = bfsmin(s);
printf("%d %d\n", getmid(x, y, g[miny]), getmid(s, t, f[miny])); //连中点
}
void getmax() {
printf("%d %d %d ", max, maxx, maxy);
printf("%d %d\n", bfsmax(maxx), bfsmax(maxy)); //连端点
}
int main() {
n = in();
int x, y;
for(int i = 1; i < n; i++) x = in(), y = in(), add(x, y), add(y, x);
predoit();
getmin();
getmax();
return 0;
}

P3596 [POI2015]MOD的更多相关文章

  1. POI2015 解题报告

    由于博主没有BZOJ权限号, 是在洛咕做的题~ 完成了13题(虽然有一半难题都是看题解的QAQ)剩下的题咕咕咕~~ Luogu3585 [POI2015]PIE Solution 模拟, 按顺序搜索, ...

  2. luogu4383 [八省联考2018]林克卡特树(带权二分+dp)

    link 题目大意:给定你 n 个点的一棵树 (边有边权,边权有正负) 你需要移除 k 条边,并连接 k 条权值为 0 的边,使得连接之后树的直径最大 题解: 根据 [POI2015]MOD 那道题, ...

  3. [Poi2015]

    [POI2015]Łasuchy 一看以为是sb题 简单来说就是每个人获得热量要尽量多 不能找别人 首先这道题好像我自己找不到NIE的情况 很容易想到一个优化 如果一个数/2>另一个数 那么一定 ...

  4. [POI2015]CZA

    [POI2015]CZA p很小,讨论 p=0... p=1... p=2:n-1放左或者放右两种情况,剩下怎么放是固定的,模拟然后判断即可 p=3: 正着做要状压,类似放书和排座位那些题,考虑以某个 ...

  5. POI2015题解

    POI2015题解 吐槽一下为什么POI2015开始就成了破烂波兰文题目名了啊... 咕了一道3748没写打表题没什么意思,还剩\(BZOJ\)上的\(14\)道题. [BZOJ3746][POI20 ...

  6. 函数mod(a,m)

    Matlab中的函数mod(a,m)的作用: 取余数 例如: mod(25,5)=0; mod(25,10)=5; 仅此.

  7. ORACLE 数据库 MOD 函数用法

    1.求2和1的余数. Select mod(2,1) from dual: 2能被1整除所以余数为0. 2.MOD(x,y)返回X除以Y的余数.如果Y是0,则返回X的值. Select mod(2,0 ...

  8. 黑科技项目:英雄无敌III Mod <<Fallen Angel>>介绍

    英雄无敌三简介(Heroes of Might and Magic III) 英3是1999年由New World Computing在Windows平台上开发的回合制策略魔幻游戏,其出版商是3DO. ...

  9. BZOJ 4385: [POI2015]Wilcze doły

    4385: [POI2015]Wilcze doły Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 648  Solved: 263[Submit][ ...

随机推荐

  1. XML文件中“>”和“<”的转码

    在xml文件中,大于号“>”和小于号“<”是不能被直接识别的,需要经过转码才可以被识别,转码后的格式如下: < < 小于 > > 大于

  2. fcntl详细说明

    功能描述:根据文件描述词来操作文件的特性. #include <unistd.h>#include <fcntl.h> int fcntl(int fd, int cmd);  ...

  3. MAVEN学习总结1

    一.安装Maven插件 下载下来的maven插件如下图所示:,插件存放的路径是:E:/MavenProject/Maven2EclipsePlugin

  4. 【bzoj3940】[Usaco2015 Feb]Censoring

    [题目描述] FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S.他有一个包含n个单词的列表,列表里的n个单词 记为t_1...t_N.他希望从S中删除这些单词.  FJ每次 ...

  5. php opcode

    opcode是计算机指令中的一部分,用于指定要执行的操作, 指令的格式和规范由处理器的指令规范指定. 除了指令本身以外通常还有指令所需要的操作数,可能有的指令不需要显式的操作数. 这些操作数可能是寄存 ...

  6. Druid配置属性列表及含义

    前两天,在排查springBoot使用双数据源出现的运行一段时候出现了数据库连接断开的问题的时候,查了很多关于Druid数据库连接池配置的文章,虽然最后问题的原因不是属性配置的问题,也可以说是 属性配 ...

  7. jQuery 对象和 json 之间的转换

    JSON.parse() json 转换成 对象 JSON.stringify() 对象转换成json 想问下广大网友大神 js 里面有数组转换或者转换成数组的函数么?小弟等--

  8. ROS indigo Ubuntu14.04 安装问题

    错误信息:Unpacking ros-indigo-desktop-full (1.1.6-0trusty-20181006-135515-0800) ... Errors were encounte ...

  9. Part4_lesson1---Bootloader设计蓝图

    1.bootloader的作用 2.u-boot是bootloader业界的老大 u-boot分为自主模式和开发模式 3.建立U-boot工程 uboot不能在window下面进行解压,因为在wind ...

  10. HDU 4118 Holiday's Accommodation (dfs)

    题意:给n个点,每个点有一个人,有n-1条有权值的边,求所有人不在原来位置所移动的距离的和最大值. 析:对于每边条,我们可以这么考虑,它的左右两边的点数最少的就是要加的数目,因为最好的情况就是左边到右 ...