一道树的直径

树网的核 BZOJ原题链接

树网的核 洛谷原题链接

消防 BZOJ原题链接

消防 洛谷原题链接

一份代码四倍经验,爽

显然要先随便找一条直径,然后直接枚举核的两个端点,对每一次枚举的核遍历核上的每个点,用\(dfs\)求出核外节点到核的最大值即可,时间复杂度为\(O(n^3)\),这在\(NOIP\)的原数据范围下是可以过的,但对于数据加强版就必须要优化了。

发现当枚举到直径上的某个点时,核的另一端在不超过\(s\)的前提下显然越远越好。这样就直接优化掉一个\(n\)了,但我们还可以继续优化。

设直径上的点为\(u_1,u_2,\dots,u_t\),当前枚举到的核的两端点为\(x_i,x_j\)。

根据直径的最长性,我们可以发现对于该核的偏心距实际上就是\(\max\{\max\limits_{k=1}^{t}\{d[u_k]\},dis(u_1,x_i),dis(x_j,u_t)\}\),数组\(d\)表示直径外节点(不经过直径上的点)到\(u_k\)的最大值,\(dis\)表示两点间的距离。

而\(\max\limits_{k=1}^{t}\{d[u_k]\}\)显然是个定值,至于\(dis\),我们可专门剖出直径上的所有边,然后用在枚举核的左端点时用两个变量维护即可,时间复杂度\(O(n)\)。

#include<cstdio>
using namespace std;
const int N = 5e5 + 10;
struct dd {
int dis, x;
};
dd D[N], a[N];
int fi[N], di[N << 1], da[N << 1], ne[N << 1], l, ma;
bool v[N];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c<'0' || c>'9'; c = getchar())
p |= c == '-';
for (; c >= '0'&&c <= '9'; c = getchar())
x = x * 10 + (c - '0');
return p ? -x : x;
}
inline int maxn(int x, int y)
{
return x > y ? x : y;
}
inline int minn(int x, int y)
{
return x < y ? x : y;
}
inline void add(int x, int y, int z)
{
di[++l] = y;
da[l] = z;
ne[l] = fi[x];
fi[x] = l;
}
void dfs(int x, int fa, int dis, int la)
{
int i, y;
if (dis > ma)
{
ma = dis;
D[0].x = x;
}
D[x].x = fa;
D[x].dis = la;
for (i = fi[x]; i; i = ne[i])
{
y = di[i];
if (y != fa)
dfs(y, x, dis + da[i], da[i]);
}
}
void dfs_2(int x, int dis)
{
int i, y;
v[x] = 1;
if (dis > ma)
ma = dis;
for (i = fi[x]; i; i = ne[i])
{
y = di[i];
if (!v[y])
dfs_2(y, dis + da[i]);
}
}
int main()
{
int i, j, n, m, x, y, z, s = 0, k = 0, tail = 0, head = 0, an = 1e9;
n = re();
m = re();
for (i = 1; i < n; i++)
{
x = re();
y = re();
z = re();
add(x, y, z);
add(y, x, z);
}
dfs(1, 0, 0, 0);
ma = 0;
dfs(D[0].x, 0, 0, 0);
for (i = D[0].x; i; i = D[i].x)
{
v[i] = 1;
a[++k].x = i;
a[k].dis = D[i].dis;
}
ma = 0;
for (i = 1; i <= k; i++)
dfs_2(a[i].x, 0);
for (j = 1; j < n; j++)
if (s + a[j].dis <= m)
s += a[j].dis;
else
break;
for (i = j; i < n; i++)
tail += a[i].dis;
an = minn(an, maxn(ma, maxn(head, tail)));
for (i = 1; i < n; i++)
{
s -= a[i].dis;
head += a[i].dis;
for (; j < n; j++)
if (s + a[j].dis <= m)
{
s += a[j].dis;
tail -= a[j].dis;
}
else
break;
an = minn(an, maxn(ma, maxn(head, tail)));
}
printf("%d", an);
return 0;
}

BZOJ1999或洛谷1099&BZOJ2282或洛谷2491 树网的核&[SDOI2011]消防的更多相关文章

  1. 洛谷P1099 BZOJ1999 树网的核 [搜索,树的直径]

    洛谷传送门,BZOJ传送门 树网的核 Description 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(treenetwork),其中V ...

  2. [洛谷P2491] [SDOI2011]消防

    洛谷题目链接:[SDOI2011]消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超 ...

  3. [BZOJ1999] 树网的核 [数据加强版] (树的直径)

    传送门 如果只是想验证算法正确性这里是洛谷数据未加强版 Description 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(treenet ...

  4. [BZOJ1999][codevs1167][Noip2007]Core树网的核

    [BZOJ1999][codevs1167][Noip2007]Core树网的核 试题描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(t ...

  5. 【BZOJ2282】[Sdoi2011]消防 树形DP+双指针法+单调队列

    [BZOJ2282][Sdoi2011]消防 Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这 ...

  6. bzoj1999 (洛谷1099) 树网的核——dfs

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1999  https://www.luogu.org/problemnew/show/P109 ...

  7. 洛谷 1099 ( bzoj 1999 ) [Noip2007]Core树网的核

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1999 <算法竞赛进阶指南>346页.https://www.cnblogs.co ...

  8. 洛谷1099 [NOIP2007] 树网的核

    链接https://www.luogu.org/problemnew/show/P1099 题目描述 设T=(V,E,W)是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称TTT为 ...

  9. 【新知识】队列&bfs【洛谷p1996约瑟夫问题&洛谷p1451求细胞数量】

    (是时候为五一培训准备真正的技术了qwq) part1  队列(FIFO) 算法简介: FIFO:First In First Out(先进先出) 队列是限定在一端进行插入,另一端进行删除的特殊线性表 ...

随机推荐

  1. python错题整理

    1.列表list去重 l1 = [1,1,2,3,5,5,4,4,4,5,6] set1 = set(l1) # print(set1) # set是集合 l2 = list(set1) # 将集合转 ...

  2. 定时删除文件夹"$1"下最后修改时间大于当前时间"$2"天的文件

    shell 脚本: #!/bin/bash now=`date "+%Y-%m-%d_%H:%M:%S"`      #获取当前时间 echo "当前时间: " ...

  3. express返回html文件

    [express返回html文件] app.engine(ext, callback) 方法即可创建一个你自己的模板引擎.其中,ext 指的是文件扩展名.callback 是模板引擎的主函数,接受文件 ...

  4. 【Django】ORM操作MySQL数据库遇到的一些问题

    关于查询操作: 1.exact和iexact exact相当于=   iexact相当于like(但是这里的like和数据库的不一样,没有给后面条件加上%%所以这里like和=的作用相似) artic ...

  5. elasticsearch 不同集群数据同步

    采用快照方式 1.源集群采用NFS,注意权限 2.共享目录完成后,在所有ES服务器上挂载为同一目录 3.创建快照仓库 put _snapshot/my_backup{ "type" ...

  6. jakson

    Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行JSON和Java对象转换,下面给出一些Jackson的J ...

  7. RocketMQ-quickstart(批量消费)

    一.专业术语 Producer 消费生产者,负责产生消息,一般由业务系统负责产生消息 Consumer 消息消费者,负责消费消息,一般是后台系统负责异步消费 Push Consumer Consume ...

  8. HDU 6315 Naive Operations(线段树区间整除区间)

    Problem DescriptionIn a galaxy far, far away, there are two integer sequence a and b of length n.b i ...

  9. UVa 548 Tree(二叉树最短路径)

    You are to determine the value of the leaf node in a given binary tree that is the terminal node of ...

  10. [Codeforces_713A]Sonya and Queries

    题目链接 http://codeforces.com/problemset/problem/713/A 题意 三种操作: +  ai 集合里加一个整数ai,相同数记为多个.  -  ai 集合里减一个 ...