Description:

设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各边长度的集合,并设T有n个结点。

路径:树网中任何两结点a,b都存在唯一的一条简单路径,用d(a, b)表示以a, b为端点的路径的长度,它是该路径上各边长度之和。我们称d(a, b)为a, b两结点间的距离。

  D(v, P)=min{d(v, u), u为路径P上的结点}。

树网的直径:树网中最长的路径成为树网的直径。对于给定的树网T,直径不一定是唯一的,但可以证明:各直径的中点(不一定恰好是某个结点,可能在某条边的内部)是唯一的,我们称该点为树网的中心。

偏心距ECC(F):树网T中距路径F最远的结点到路径F的距离,即

ECC(F)=max{d(v, F),v∈V}

任务:对于给定的树网T=(V, E, W)和非负整数s,求一个路径F,他是某直径上的一段路径(该路径两端均为树网中的结点),其长度不超过s(可以等于s),使偏心距ECC(F)最小。我们称这个路径为树网T=(V, E, W)的核(Core)。必要时,F可以退化为某个结点。一般来说,在上述定义下,核不一定只有一个,但最小偏心距是唯一的。

下面的图给出了树网的一个实例。图中,A-B与A-C是两条直径,长度均为20。点W是树网的中心,EF边的长度为5。如果指定s=11,则树网的核为路径DEFG(也可以取为路径DEF),偏心距为8。如果指定s=0(或s=1、s=2),则树网的核为结点F,偏心距为12。

(图好像咕咕咕了)

Input:

输入文件core.in包含n行:

第1行,两个正整数n和s,中间用一个空格隔开。其中n为树网结点的个数,s为树网的核的长度的上界。设结点编号以此为1,2,……,n。

从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。

Output:

输出文件core.out只有一个非负整数,为指定意义下的最小偏心距。

思路:

找到最长链后暴力枚举可以过掉NOIP的测试数据,但这个算法太咸鱼了 我们显然不能这么咸鱼下去对不对?

考虑贪心,找到直径后枚举一个起点,然后终点明显越远越好可以直接确定,然后从每个节点出发求偏心距,复杂度N2

也可以对偏心距进行二分枚举答案然后求直径上的核,复杂度NlogN

但复杂度可以到On

预处理出从直径上的每个节点出发,能到达最远点的距离d,并用前缀和预处理出直径上两两点间的距离

那么拿一个长度为s的滑动窗口扫一遍直径求出最小值就行了

没了

#include<bits/stdc++.h>
using namespace std;
const int N = ; int head[N], now = ;
struct edges{
int to, next, w;
}edge[N<<];
void add(int u, int v, int w){ edge[++now] = {v, head[u], w}; head[u] = now;} int n, lim, dep[N], d[N], pre[N], pos1, pos2;
bool isd[N];
int mymax(int x,int y,int z){
return max(x, y) > z ? max(x, y):z;
}
void dfs1(int x,int fa){
for(int i = head[x]; i; i = edge[i].next){
int v = edge[i].to;
if(v == fa) continue;
dep[v] = dep[x] + edge[i].w;
dfs1(v, x);
}
if(dep[x] > dep[pos1])
pos1 = x;
}
void dfs2(int x,int fa){
for(int i = head[x]; i; i = edge[i].next){
int v = edge[i].to;
if(v == fa) continue;
d[v] = d[x] + edge[i].w;
pre[v] = i;
dfs2(v, x);
}
if(d[x] > d[pos2])
pos2 = x;
}
int dis[N];
void dfs(int x, int fa){
for(int i = head[x]; i; i = edge[i].next){
int v = edge[i].to;
if(v == fa || isd[v]) continue;
dfs(v, x);
dis[x] = max(dis[x], dis[v] + edge[i].w);
}
}
int a[N], tot;
int main(){
scanf("%d%d",&n, &lim);
int x, y, z;
for(int i = ; i < n; i++){
scanf("%d%d%d",&x, &y, &z);
add(x, y, z); add(y, x, z);
}
dfs1(, -);
dfs2(pos1, -);
// cout<<pos1<<" "<<pos2<<endl;
for(int i = pos2; i; i = edge[pre[i] ^ ].to)
isd[i] = ,a[++tot] = i;
int ans = 1e9, mx = ;
for(int i = ; i <= tot; i++){
dfs(a[i], -);
mx = max(mx, dis[a[i]]);
}
int i = ;
for(int j = i; j <= tot; j++){
while(d[a[i]] - d[a[j]] > lim)
i++;
int tmp = mymax(mx, d[a[]] - d[a[i]], d[a[j]] - d[a[tot]]);
ans = min(ans, tmp);
}
printf("%d\n",ans);
return ;
}

BZOJ1999 NOIP2007 洛谷P1099 P2491 SDOI 2011的更多相关文章

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

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

  2. BZOJ1999或洛谷1099&BZOJ2282或洛谷2491 树网的核&[SDOI2011]消防

    一道树的直径 树网的核 BZOJ原题链接 树网的核 洛谷原题链接 消防 BZOJ原题链接 消防 洛谷原题链接 一份代码四倍经验,爽 显然要先随便找一条直径,然后直接枚举核的两个端点,对每一次枚举的核遍 ...

  3. [NOIP2007] 提高组 洛谷P1099 树网的核

    题目描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各边长度的集合,并 ...

  4. 洛谷 P1099 树网的核+P2491 [SDOI2011]消防

    写在前面:由于是双倍经验就放一块了,虽然数据范围差的有点大. 题目链接 题意:在树的直径上选择一条长度不超过s的路径使这条路径上的点到树上任意点的最大距离最小. 这题数据好像非常水,我写了上界n^2不 ...

  5. 洛谷 P1099 树网的核

    P1099 树网的核 题目描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W ...

  6. 洛谷P1099 树网的核

    传送门 80分 $ Floyd $ 树的直径可以通过枚举求出.直径的两个端点$ maxi,maxj $ ,由此可知对于一个点 $ k $ ,如果满足 $ d[maxi][k]+d[k][maxj]== ...

  7. 2018.11.06 洛谷P1099 树网的核(最短路+枚举)

    传送门 之前看李煜东的书一直感觉是道神题. 然后发现这题数据范围只有300?300?300? 直接上floydfloydfloyd然后暴力就完了啊. 代码: #include<bits/stdc ...

  8. BZOJ2440/洛谷P4318 [中山市选2011]完全平方数 莫比乌斯函数

    题意:找到第k个无平方因子数. 解法:这道题非常巧妙的运用了莫比乌斯函数的性质! 解法参考https://www.cnblogs.com/enzymii/p/8421314.html这位大佬的.这里我 ...

  9. 洛谷P1808 单词分类_NOI导刊2011提高(01) 字符串排序

    洛谷P1808 单词分类_NOI导刊2011提高(01) 题目描述 Oliver为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类. 两个单词可以分为一类当且 ...

随机推荐

  1. Linux命令大全(非常全,史上最全)

    最近学习Linux,最大的体验就是它的很多东西都需要由命令来进行控制,下面是我总结的一些命令,供大家参考: 系统信息   arch 显示机器的处理器架构 uname -m 显示机器的处理器架构 una ...

  2. Python3 Tkinter-Label

    1.创建 from tkinter import * root=Tk() root.title('Hello tkinter!') root.mainloop() 2.使用内置位图 from tkin ...

  3. 4.安装hive

      下载安装包并解压安装元数据库配置hive添加hvie环境变量修改hive-env.sh修改hive配置文件初始化metastore使用hive cli配置hivemestore配置hiveserv ...

  4. popen()与system()

    一.popen() 用途:执行shell命令(并读取其输出或向其发送一些输入) 特点:通过管道来与shell命令进行通信 二.system()

  5. About Dynamic Programming

    Main Point: Dynamic Programming = Divide + Remember + Guess 1. Divide the key is to find the subprob ...

  6. a3

    队名 massivehard 组员一(组长:晓辉) 今天完成了哪些任务 .整理昨天的两个功能,补些bug 写了一个初步的loyaut 还剩哪些任务: 后台的用来处理自然语言的服务器还没架. 推荐算法还 ...

  7. return语句的用法

    1.return语句的作用:a.返回一个值,这个值可以是任意类型.b.使程序返回到操作系统(即终止程序)2.java中对于一个函数,不论有没有返回值类型,都可以带有return 语句.但是区别在于,r ...

  8. Java中I/O流之轮换流

    Java 中的轮换流: 非常有用,可以把一个字节流转换成字符流. inputStreamReader, outputStreamReader Demo_1: import java.io.*; cla ...

  9. linux线程同步实例

    [Linux多线程]三个经典同步问题 - 神奕的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/lisonglisonglisong/article/details ...

  10. C# 执行bat文件

    private void RunBat(string batPath) { Process pro = new Process(); FileInfo file = new FileInfo(batP ...