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

试题描述

设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(treenetwork),其中V, E分别表示结点与边的集合,W表示各边长度的集合,并设T有n个结点。 路径:树网中任何两结点a,b都存在唯一的一条简单路径,用d(a,b)表示以a,b为端点的路径的长度,它是该路径上各边长度之和。我们称d(a,b)为a,b两结点间的距离。 一点v到一条路径P的距离为该点与P上的最近的结点的距离: d(v,P)=min{d(v,u),u为路径P上的结点}。 树网的直径:树网中最长的路径称为树网的直径。对于给定的树网T,直径不一定是唯一的,但可以证明:各直径的中点(不一定恰好是某个结点,可能在某条边的内部)是唯一的,我们称该点为树网的中心。 偏心距ECC(F):树网T中距路径F最远的结点到路径F的距离,即 。 任务:对于给定的树网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。

输入

包含n行: 第1行,两个正整数n和s,中间用一个空格隔开。其中n为树网结点的个数,s为树网的核的长度的上界。设结点编号依次为1, 2, ..., n。 从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。 所给的数据都是正确的,不必检验。

输出

只有一个非负整数,为指定意义下的最小偏心距。

输入示例


输出示例


数据规模及约定

对于70%的数据,n<=200000
对于100%的数据:n<=500000, s<2^31, 所有权值<500

(原题范围:5<=n<=300, 0<=s<=1000。边长度为不超过1000 的正整数)

题解

BZOJ 太过分了,不仅数据扩大了 1K+ 倍,还卡内存。。。

随便贪心,搞出直径、直径中点,然后向两端扩展(哪头距离对应直径端点远就选择向哪头扩展,贪心)。

所有过程只需要用 BFS。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;
#define LL long long LL read() {
LL x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 500010
#define maxm 1000010
#define maxlog 20
int n, m, far, head[maxn], next[maxm], to[maxm];
LL dist[maxm]; void AddEdge(int a, int b, LL c) {
to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
return ;
} int Q[maxn], hd, tl;
LL d[maxn];
void BFS(int s) {
memset(d, -1, sizeof(d));
hd = tl = 0; Q[++tl] = s;
d[s] = 0;
while(hd < tl) {
int u = Q[++hd];
for(int e = head[u]; e; e = next[e]) if(d[to[e]] < 0) {
d[to[e]] = d[u] + dist[e];
Q[++tl] = to[e];
}
}
return ;
} int mid1, mid2;
LL md1, md2, td;
bool done[maxn];
void getmid(int s) {
d[s] = 0; done[s] = 1;
hd = tl = 0; Q[++tl] = s;
while(hd < tl) {
int u = Q[++hd];
for(int e = head[u]; e; e = next[e]) if(!done[to[e]]) {
if(d[to[e]] > d[u] + dist[e]) {
d[to[e]] = d[u] + dist[e];
Q[++tl] = to[e]; done[to[e]] = 1;
}
else if(d[to[e]] == d[u] + dist[e]) {
mid1 = to[e]; md1 = d[to[e]];
return ;
}
else {
mid1 = u; mid2 = to[e];
md1 = d[u]; md2 = d[to[e]];
td = dist[e];
return ;
}
}
}
return ;
} LL Dep[maxn];
int dep[maxn], vis[maxn], fa[maxn];
void build(int u, int pa) {
fa[u] = pa;
for(int e = head[u]; e; e = next[e]) if(to[e] != pa) {
dep[to[e]] = dep[u] + 1;
Dep[to[e]] = Dep[u] + dist[e];
build(to[e], u);
}
return ;
} void BFS2() {
memset(d, -1, sizeof(d));
hd = tl = 0;
for(int i = 1; i <= n; i++) if(vis[i] == 4) Q[++tl] = i, d[i] = 0;
while(hd < tl) {
int u = Q[++hd];
for(int e = head[u]; e; e = next[e]) if(d[to[e]] < 0) {
d[to[e]] = d[u] + dist[e];
Q[++tl] = to[e];
}
}
return ;
} int main() {
n = read(); far = read();
for(int i = 1; i < n; i++) {
int a = read(), b = read(), c = read();
AddEdge(a, b, c);
} BFS(1);
int cnt = 0, A, B;
LL mx = 0;
bool tp = 1;
for(int i = 1; i <= n; i++) mx = max(mx, d[i]);
for(int i = 1; i <= n; i++) if(mx == d[i]) cnt++, B = i;
tp &= (cnt == 1);
BFS(B);
mx = cnt = 0;
for(int i = 1; i <= n; i++) mx = max(mx, d[i]);
for(int i = 1; i <= n; i++) if(mx == d[i]) cnt++, A = i;
tp &= (cnt == 1); getmid(A);
// printf("%lld %d %d %d %d %lld %lld %lld (%lld %lld)\n", mx, mid1, mid2, A, B, md1, md2, td, max(md1, md2 + td), max(md2, md1 + td));
if(max(md1, md2 + td) > max(md2, md1 + td)) swap(md1, md2), swap(mid1, mid2);
build(mid1, 0); vis[mid1] = 4;
// printf("mid1: %d %lld %lld\n", mid1, Dist(mid1, A), Dist(mid2, B));
int tmp = A;
while(tmp != mid1) vis[tmp] = 2, tmp = fa[tmp];
tmp = B;
while(tmp != mid1) vis[tmp] = 3, tmp = fa[tmp];
int a, b; a = b = mid1;
while(far) {
int ta = mid1, tb = mid1;
LL da, db;
for(int e = head[a]; e; e = next[e]) if(vis[to[e]] == 2) {
ta = to[e], da = dist[e]; break;
}
for(int e = head[b]; e; e = next[e]) if(vis[to[e]] == 3) {
tb = to[e], db = dist[e]; break;
}
if(Dep[A] - Dep[a] > Dep[B] - Dep[b]) {
if(da <= far) a = ta, vis[a] = 4, far -= da;
else break;
}
else {
if(db <= far) b = tb, vis[b] = 4, far -= db;
else break;
}
}
LL ans = 0;
// printf("%d %d %lld\n", a, b, Dist(a, b));
BFS2();
for(int i = 1; i <= n; i++) ans = max(ans, d[i]); printf("%lld\n", ans); return 0;
}

[BZOJ1999][codevs1167][Noip2007]Core树网的核的更多相关文章

  1. 【bzoj1999】[Noip2007]Core树网的核 树的直径+双指针法+单调队列

    题目描述 给出一棵树,定义一个点到一条路径的距离为这个点到这条路径上所有点的距离的最小值.求一条长度不超过s的路径,使得所有点到这条路径的距离的最大值最小. 输入 包含n行: 第1行,两个正整数n和s ...

  2. BZOJ_1999_[Noip2007]Core树网的核_单调队列+树形DP

    BZOJ_1999_[Noip2007]Core树网的核_单调队列+树形DP Description 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T ...

  3. [bzoj1999][noip2007]Core树网的核

    好久没写题解了.这题不算太水就写一下题解. 话说回来,虽然不水但是挺裸.可以说题意即一半题解了. 我猜粘了题面也没有人去看的,所以直接人话题意了. 给一棵树,点数1e6,(当年noip的n当然是只有3 ...

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

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

  5. [Noip2007]Core树网的核

    嘟嘟嘟 首先求树的直径两次bfs即可,实际上bfs就是最短路,因为树上路径是唯一的,所以用任何一种遍历方法都行(spfa和dijkstra当然也可以). 可以证明,只要求出任意一条直径就行了,为什么呢 ...

  6. bzoj 1999: [Noip2007]Core树网的核【树的直径+单调队列】

    我要懒死了,所以依然是lyd的课件截图 注意是min{max(max(d[uk]),dis(u1,ui),dis(uj,un))},每次都从这三个的max里取min #include<iostr ...

  7. 【BZOJ1999】【NOIP2007】树网的核 单调队列优化DP

    题目描述 题目很长,大家自己去看吧. bzoj vijos 原题\(n\leq 300\) 加强版\(n\leq 500000\) 题解 这种东西当然要猜结论的啦,否则会比较麻烦. 结论1:如果有很多 ...

  8. 【noip2007】树网的核

    题解: 首先我们要知道一个性质:如果有多条直径 这个核不论在哪条直径上 答案都是一样的 这样我们就可以随便找一条直径 在这条直径上枚举核的位置 并且dfs预处理maxlon[i] (i在直径上) 表示 ...

  9. 【DFS好题】BZOJ1999- [Noip2007]Core树网的核(数据加强版)

    NOIP的数据好水,一开始有好几个错结果NOIP数据就水过了?? [题目大意] 求无根树的直径上一段不超过S长的链,使得偏心距最小.具体概念见原题. [思路] 首先明确几个性质: (1)对于树中的任意 ...

随机推荐

  1. Android中如何使用Intent在Activity之间传递对象[使用Serializable或者Parcelable]

    http://blog.csdn.net/cjjky/article/details/6441104 在Android中的不同Activity之间传递对象,我们可以考虑采用Bundle.putSeri ...

  2. awk sed

    awk -F '|' '{print $3","$4","$5}' cred.ts | sed 's/-//g'

  3. 自然语言18.2_NLTK命名实体识别

    QQ:231469242 欢迎nltk爱好者交流 http://blog.csdn.net/u010718606/article/details/50148261 NLTK中对于很多自然语言处理应用有 ...

  4. yourphp读取不到hits

    源代码 <YP:list name="Article" order="id desc" catid="37" limit=" ...

  5. jquery.cookie使用方法

    jquery.cookie 使用方法 一个轻量级的 cookie 插件,可以读取.写入.删除 cookie . jquery.cookie.js 的配置 首先包含 jQuery 的库文件,在后面包含 ...

  6. aufomaper Queryable Extensions ProjectTo

    When using an ORM such as NHibernate or Entity Framework with AutoMapper's standard Mapper.Map funct ...

  7. python字符类型的一些方法

    python 字符串和字节互转换.bytes(s, encoding = "utf8") str(b, encoding = "utf-8") i.isspac ...

  8. F5负载均衡的初识和基本配置

    目前全球范围内应用比较广泛的负载均衡设备为美国的F5.F5于2000年底进驻中国,在国内业界,F5负载均衡产品已经成为了主流负载均衡技术的代名词.下面我们对F5负载均衡设备做一个基本介绍,方便大家去认 ...

  9. _ATTRIBUTE__ 你知多少?

    from:http://www.cnblogs.com/astwish/p/3460618.html __ATTRIBUTE__ 你知多少? GNU C 的一大特色就是__attribute__ 机制 ...

  10. Hibernate 应用

    完善的持久化层应该达到以下目标: 1.代码可重用性高,能够完成所有的数据库访问操作. 2.如果有需要的话,能够支持多种数据库平台. 3.具有相对独立性,当持久化层的实现发生变化,不会影响上层的实现. ...