【题目描述】

设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的距离, 即 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。

【输入格式】

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

【输出格式】

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

【样例输入】

5 2
1 2 5
2 3 2
2 4 4
2 5 3

【样例输出】

5
【分析】

首先找到一个树的直径。方法是:从1点出发,找到距离1最远的点,记为x。然后从x出发,所搜索到的最远路径就是树的直径。

然后我们用搜索的方法计算每个点到直径的最短距离dist。

之后在直径上枚举路径的起点和终点。找到最小的偏心距。

#include <stdio.h>
#include <string.h>
#include <limits.h>
#define MAXN 310
struct tnode {int num;tnode *next;
} g[MAXN],*t;
int q[MAXN * 3],list[MAXN],loc[MAXN],dist[MAXN],from[MAXN],dis[MAXN],di[MAXN][MAXN],xdis[MAXN][MAXN];
int n,l,r,s,x,y,z,tot,ans;
bool v[MAXN],in_tree[MAXN];
void insert(int x,tnode &p) {t = new(tnode);t->num = x;t->next = p.next;p.next = t;
}
void dfs(int father,int x) {tnode *tt;tt = g[x].next;while (tt != NULL) {int y = tt->num;if (!in_tree[y])if (dist[x] + di[x][y] < dist[y]) {dist[y] = dist[x] + di[x][y];from[y] = father;dfs(father,y);}tt = tt->next;}
}
int main() { scanf("%d%d",&n,&s);for (int i = 1;i < n;++i) {scanf("%d%d%d",&x,&y,&z);insert(x,g[y]);insert(y,g[x]);di[x][y] = z;di[y][x] = z;}q[0] = 1;v[1] = 1;while (l <= r) {x = q[l];t = g[x].next;while (t != NULL) {y = t->num;if (y != from[x])if (dis[y] < di[x][y] + dis[x]) {dis[y] = di[x][y] + dis[x];from[y] = x;if (!v[y]) {q[++r] = y;v[y] = 1;}}t = t->next;}++l;v[x] = 0;}z = 0;for (int i = 1;i <= n;++i)if (dis[i] > z) {z = dis[i];x = i;}memset(from,0,sizeof(from));memset(v,0,sizeof(v));v[x] = 1;memset(dis,0,sizeof(dis));q[0] = x;v[x] = 1;l = r = 0;while (l <= r) {x = q[l];t = g[x].next;while (t != NULL) {y = t->num;if (from[x] != y)if (dis[y] < di[x][y] + dis[x]) {dis[y] = di[x][y] + dis[x];from[y] = x;if (!v[y]) {q[++r] = y;v[y] = 1;}}t = t->next;}++l;v[x] = 0;}z = 0;for (int i = 1;i <= n;++i)if (dis[i] > z) {z = dis[i];x = i;}list[++tot] = x;while (from[x]) {x = from[x];list[++tot] = x;}for (int i = 1;i <= tot;++i) {loc[list[i]] = i;in_tree[list[i]] = 1;}for (int i = 1;i <= tot;++i)for (int j = i + 1;j <= tot;++j)xdis[i][j] = xdis[i][j - 1] + di[list[j - 1]][list[j]];memset(from,0,sizeof(from));for (int i = 1;i <= n;++i)if (!in_tree[i])dist[i] = INT_MAX;for (int i = 1;i <= tot;++i)dfs(list[i],list[i]);ans = INT_MAX;for (int st = 1;st <= tot;++st)for (int en = st;en <= tot;++en) {if (xdis[st][en] > s)break;int te_ans = 0;for (int i = 1;i <= n;++i)if (!in_tree[i]) {if (dist[i] > te_ans)te_ans = dist[i];} else {x = loc[i];if (x < st) {if (dist[i] + xdis[x][st] > te_ans)te_ans = dist[i] + xdis[x][st];}if (x > en) {if (dist[i] + xdis[en][x] > te_ans)te_ans = dist[i] + xdis[en][x];}}if (te_ans < ans)ans = te_ans;}printf("%d\n",ans);return 0;
}

转载于:https://www.cnblogs.com/sephirothlee/archive/2010/10/14/1850939.html

[O(N)的我不会]树网的核相关推荐

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

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

  2. 树网的核(codevs 1167)

    题目描述 Description [问题描述] 设 T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我 们称T 为树网(treenetwork),其中V, E分 ...

  3. NOIP2007 树网的核 [BZOJ2282][Sdoi2011]消防

    NOIP2007 树网的核 树的直径的最长性是一个很有用的概念,可能对一些题都帮助. 树的直径 给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和.树中最远的两个节点之 ...

  4. 树网的核 Vijos1362 NOIP2007 树结构 直径 暴搜

    题面在最下方. 树结构的题做多了就会发现,本题所谓的树网的核(一段偏心距ECC最小的路径)一定是在树的直径上的. 我刚开始做的时候没想到这个,然后写了三个dfs讨论每条直径 Orz 其实只要认识到了这 ...

  5. VIJOS 1362 树网的核

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

  6. 2017.3.21 树网的核 思考记录

    把这个noip的题搞出来了.. 不是很难,而且我的要求也比较高(虽然以前看到这种题都是直接看题解,因为太复杂不会) 虽然搞出来在luogu 的noip数据 A了,但bzoj还是T了.理论上应该是O(n ...

  7. code1167 树网的核

    floyd+枚举 看点: 1.floyd同时用数组p记录转移节点k,这样知道线段的端点u v就可以得到整条线段 2.任意一点c到线段a b的距离=(d[a][c]+d[c][b]-d[a][b])/2 ...

  8. 洛谷P1099 树网的核

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

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

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

最新文章

  1. centos7.9 配置nginx实现前后端分离
  2. 有人工裁判,就会有争执
  3. 图解 windbg设置符号文件路径和使用入门
  4. WPF/MVVM 快速开发
  5. (转)API SOCKET基础(一) TCP建立连接并通信
  6. 哈希函数(Hash Functions - 散列函数)的基本介绍(SHA-2,SHA-256,MD-5,Scrypt,BCrypt等)
  7. React 组件开发 传参(详解)。
  8. 三星平板显示无法连接网络连接服务器,三星p600平板电脑无法连接无线网络该怎么办?...
  9. C# Socket实现两台电脑通信(三)
  10. 小白也能懂的hadoop生态圈,很黄很暴力!
  11. Paper翻译:《A Novel Convolutional Neural Network Based Model for Recognition and Classification of App》
  12. CAN 总线通信 简要概括
  13. c语言 判断互质,[经典算法] 找出某数以内与其互质的数
  14. 详解Dell EMC发布的PowerMax存储和R系列计算系统
  15. 基于Tensorflow 2.x手动复现BERT
  16. MySQL之——崩溃-修复损坏的innodb:innodb_force_recovery
  17. 【硬件设计的工具、计算器】
  18. 计算机无法连接打印机主机,电脑主机连不上网络打印机
  19. Automation Anywhere A360 Advance Certified认证 RPA Professional 真题和详细攻略
  20. 猴子分桃的题目:海滩上有一堆桃子,五只猴子来分。第一只猴子把这堆桃子凭据分为五份,多了 一个,这只猴子把多的一个扔入海中,拿走了一份。第二只猴子把剩下的桃子又平均分 成五份,又多了一个,

热门文章

  1. SpringBoot 学习 | raibaby Halo v0.4.3 漏洞分析-Ali0th
  2. MySQL 性能优化及常用命令
  3. Linux运维基础(硬件和操作系统)
  4. 序列化中的[NonSerialized]字段 -转
  5. Python~第三方模块
  6. Log4j 2使用教程转
  7. 虚拟化--027 VMware vCenter Server Heartbeat 6.5安装教程
  8. error: jump to label ‘XXXX’ [-fpermissive]
  9. 计算机网络基础(路由原理)
  10. Windows API获取系统配置文件的配置参数