[Noip2007]Core树网的核
嘟嘟嘟
首先求树的直径两次bfs即可,实际上bfs就是最短路,因为树上路径是唯一的,所以用任何一种遍历方法都行(spfa和dijkstra当然也可以)。
可以证明,只要求出任意一条直径就行了,为什么呢?考虑一下,如果我们在直径上选了一段,那么最远偏心距可肯定是到直径两端的最大值,和直径外的点无关,只和直径的长度有关。
于是我们求完了直径。然后在直径上搞一搞:很容易想到,如果当前选了一段长度为a,他还可以延伸为b,且a < b < s,那么b的答案一定比a优。因此我们建立一个双指针L,R,代表当前选取的一段的左右端点,当L一定时,R要尽量远,如果超出了s,L指针就向前挪一个节点。其中dis数组就充当了前缀和数组的作用,然后每一次都尝试用max(dis[L], dis[end] - dis[R])更新答案,时间复杂度为O(n)。
需要注意的是,因为我们存路径都是反向存的,因此上面实际上应该是max(dis[R], dis[end] - dis[L]),而且跳的时候不是L++,R++,而是L = pre[L], R = pre[R].
别忘了还有一种情况:就是直径长度小于s,此时的答案应该是不在直径上的点到直径的最大值,只要对于直径上每一个节点向外dfs找就行,因为每一个节点只会遍历一次,所以时间复杂度还是O(n)。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a) memset(a, 0, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 5e5 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n, s; 38 vector<int> v[maxn], c[maxn]; 39 40 bool vis[maxn]; 41 int dis[maxn], pre[maxn], w[maxn]; 42 int bfs(int s) 43 { 44 Mem(vis); Mem(pre); Mem(w); Mem(dis); 45 queue<int> q; q.push(s); 46 vis[s] = 1; 47 dis[s] = 0; 48 while(!q.empty()) 49 { 50 int now = q.front(); q.pop(); 51 for(int i = 0; i < (int)v[now].size(); ++i) 52 { 53 if(!vis[v[now][i]]) 54 { 55 vis[v[now][i]] = 1; 56 dis[v[now][i]] = dis[now] + c[now][i]; 57 pre[v[now][i]] = now; 58 w[v[now][i]] = c[now][i]; 59 q.push(v[now][i]); 60 } 61 } 62 } 63 int Max = -1, pos; 64 for(int i = 1; i <= n; ++i) if(dis[i] > Max) Max = dis[i], pos = i; 65 return pos; 66 } 67 68 int ans = INF; 69 70 int dfs(int now, int x) 71 { 72 int ret = -1; 73 for(int i = 0; i < (int)v[now].size(); ++i) 74 { 75 if(!vis[v[now][i]]) 76 { 77 vis[v[now][i]] = 1; 78 ret = max(ret, dfs(v[now][i], x + c[now][i])); 79 } 80 } 81 return max(ret, x); 82 } 83 void solve(int b, int a) 84 { 85 Mem(vis); 86 ans = -1; 87 for(int i = b; i; i = pre[i]) {vis[pre[i]] = vis[i] = 1; ans = max(ans, dfs(i, 0));} 88 write(ans); enter; 89 } 90 91 int main() 92 { 93 n = read(); s = read(); 94 for(int i = 1; i < n; ++i) 95 { 96 int x = read(), y = read(), co = read(); 97 v[x].push_back(y); c[x].push_back(co); 98 v[y].push_back(x); c[y].push_back(co); 99 } 100 int a = bfs(1); 101 int b = bfs(a); 102 if(s >= dis[b]) {solve(b, a); return 0;} 103 int L = b, R = b; 104 for(int i = b; i; i = pre[i]) 105 { 106 while(L != R && dis[L] - dis[R] + w[i] > s) L = pre[L]; 107 if(dis[L] - dis[R] + w[i] > s) L = pre[i]; 108 R = pre[i]; 109 ans = min(ans, max(dis[R], dis[b] - dis[L])); 110 } 111 write(ans); enter; 112 return 0; 113 }
View Code
转载于:https://www.cnblogs.com/mrclr/p/9617934.html
[Noip2007]Core树网的核相关推荐
- bzoj 1999: [Noip2007]Core树网的核【树的直径+单调队列】
我要懒死了,所以依然是lyd的课件截图 注意是min{max(max(d[uk]),dis(u1,ui),dis(uj,un))},每次都从这三个的max里取min #include<iostr ...
- [NOIP2007] 提高组 洛谷P1099 树网的核
题目描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各边长度的集合,并 ...
- NOIP2007 树网的核 [BZOJ2282][Sdoi2011]消防
NOIP2007 树网的核 树的直径的最长性是一个很有用的概念,可能对一些题都帮助. 树的直径 给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和.树中最远的两个节点之 ...
- 树网的核 Vijos1362 NOIP2007 树结构 直径 暴搜
题面在最下方. 树结构的题做多了就会发现,本题所谓的树网的核(一段偏心距ECC最小的路径)一定是在树的直径上的. 我刚开始做的时候没想到这个,然后写了三个dfs讨论每条直径 Orz 其实只要认识到了这 ...
- [O(N)的我不会]树网的核
[题目描述] 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(treenetwork),其中V, E分别表示结点与边的集合,W表示各边长度的集 ...
- 树网的核(codevs 1167)
题目描述 Description [问题描述] 设 T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我 们称T 为树网(treenetwork),其中V, E分 ...
- VIJOS 1362 树网的核
描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各边长度的集合,并设T ...
- NOIP2007 树网的核
传送门 最近搞一搞树型结构--毕竟自己树的知识学的太垃圾了. 首先这道题非常明显要求树的直径.树的直径有好多好多种求法,这里我选择了一位dalao的非常简洁的dfs的方法.先看一下代码. void d ...
- 2017.3.21 树网的核 思考记录
把这个noip的题搞出来了.. 不是很难,而且我的要求也比较高(虽然以前看到这种题都是直接看题解,因为太复杂不会) 虽然搞出来在luogu 的noip数据 A了,但bzoj还是T了.理论上应该是O(n ...
- code1167 树网的核
floyd+枚举 看点: 1.floyd同时用数组p记录转移节点k,这样知道线段的端点u v就可以得到整条线段 2.任意一点c到线段a b的距离=(d[a][c]+d[c][b]-d[a][b])/2 ...
最新文章
- jbpm知识点——tasknode
- 会说话的狗狗本电脑版_会说话的电脑有点酷!惠普星14帮你解锁“偷懒”新姿势_惠普 星 14 2020(i5 1135G7/16GB/512GB/MX450)_笔记本新闻...
- 一致性哈希算法及其在分布式系统中的应用
- 分享 - Social.framework
- python判断计算机是否有网络连接
- 设计模式(一)--单一职责模式(衡量接口或类设计)
- html输入参数,传递输入参数,通过Html.ActionLink
- alien rpm deb,ubuntu下安装jdk过程及遇到的问题
- 经济学人:数据经济虽好,可是仍需补钙
- c#使用word、excel、pdf ——转
- 杀毒软件可以查杀已知的计算机病毒,杀毒软件可以查杀( )。
- 纯HTML标签详解(摘自阿里西西)
- 2015 年度新增开源软件排名TOP100
- 电驴emule使用教程
- mysql 语法大全
- 轻松创建天龙八部的场景
- CSS3实现图片翻转效果
- 解决 Windows系统 快捷方式 图标 变成 白色方块
- c语言:模拟用户密码登录
- Android 修改SIM卡默认VOLTE值
热门文章
- 5.2自动扫描及装配数据
- 【渝粤教育】国家开放大学2018年春季 0032-22T农业经济学 参考试题
- 【渝粤教育】广东开放大学 演绎娱乐经验管理 形成性考核 (49)
- ubuntu16.04 下ROS操作系统学习笔记(一)ROS-kinetic安装
- freeswitch 一些坑
- 慢慢人生路,学点Jakarta基础-集合类
- 快捷添加请求头的方法
- Unity编辑器扩展之RequireComponent等详解
- [转]Mathtype中批量修改公式的字体和大小
- 【iCore4 双核心板_FPGA】例程一:GPIO输出实验——点亮LED