题意:在基环树上找一点,使得这个点到所有点的距离最大值最小。这个点可以在某条边上。

解:很容易想到找出直径然后/2对吧...这里的直径是指任意两点间最短距离的最大值。

然而我这个SB冥思苦想了半天之后想到了一个傻逼绝伦的做法:枚举边!

这个点一定在某条边上。

所以知道边的两端点最长延伸多长即可。

如果是子树里的边,很显然下面那个点就是子树内最长链。而上面那个点就是子树外最长链或深度 + 根节点在环上最长延伸距离

如果是环上的边,就是两端点子树最长链或者环上延伸的最长距离

值得注意的是,这两个"环上最长延伸距离"并不是一样的。

因为前者只有一个点在环上,没有别的环上的点跟它竞争。

而后者要跟环上另一个点相互竞争。所以还要分两种情况。

具体实现上,首先找环,然后每个子树做两次树形DP,第二次是二次扫描与换根法。

然后把环的信息提取出来DP,利用单调队列来求最长延伸距离,反正我写了4个......

最后枚举边判定。

反正就是仔细写,耐心Debug...

(为什么别人1k就能A而我要5k啊...)

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <stack>
  4. #include <cstring>
  5.  
  6. typedef long long LL;
  7. const int N = ;
  8.  
  9. struct Edge {
  10. int nex, v;
  11. LL len;
  12. }edge[N << ]; int top = ;
  13.  
  14. int e[N], n, cir[N], tc, p[N], head, tail, fr[N], nex[N], pre[N];
  15. std::stack<int> S;
  16. bool vis[N], is_cir[N];
  17. LL d[N], len1[N], len2[N], lenup[N], dis[N], p2[N], sum[N], Long[N], Long_l[N], Long_r[N];
  18.  
  19. inline void add(int x, int y, LL z) {
  20. top++;
  21. edge[top].v = y;
  22. edge[top].len = z;
  23. edge[top].nex = e[x];
  24. e[x] = top;
  25. return;
  26. }
  27.  
  28. void Df(int x, int f) {
  29. vis[x] = ;
  30. S.push(x);
  31. for(int i = e[x]; i && !vis[]; i = edge[i].nex) {
  32. int y = edge[i].v;
  33. if(y == f) {
  34. continue;
  35. }
  36. if(vis[y]) {
  37. vis[] = ;
  38. while(x != y) {
  39. x = S.top();
  40. S.pop();
  41. is_cir[x] = ;
  42. cir[++tc] = x;
  43. }
  44. return;
  45. }
  46. Df(y, x);
  47. }
  48. if(vis[]) {
  49. return;
  50. }
  51. S.pop();
  52. vis[x] = ;
  53. return;
  54. }
  55.  
  56. void DFS_1(int x, int f, int aim) { // get d len1 len2
  57. if(!fr[x]) {
  58. fr[x] = fr[f];
  59. }
  60. for(int i = e[x]; i; i = edge[i].nex) {
  61. int y = edge[i].v;
  62. if(y == f || is_cir[y]) {
  63. if(cir[aim] == y) {
  64. dis[aim] = edge[i].len;
  65. nex[x] = y;
  66. pre[y] = x;
  67. }
  68. continue;
  69. }
  70. d[y] = d[x] + edge[i].len;
  71. DFS_1(y, x, aim);
  72. if(len1[x] < len1[y] + edge[i].len) {
  73. len2[x] = len1[x];
  74. len1[x] = len1[y] + edge[i].len;
  75. }
  76. else if(len2[x] < len1[y] + edge[i].len) {
  77. len2[x] = len1[y] + edge[i].len;
  78. }
  79. }
  80. return;
  81. }
  82.  
  83. void DFS_2(int x, int f) {
  84. for(int i = e[x]; i; i = edge[i].nex) {
  85. int y = edge[i].v;
  86. if(y == f || is_cir[y]) {
  87. continue;
  88. }
  89. if(len1[y] + edge[i].len == len1[x]) {
  90. lenup[y] = std::max(lenup[x], len2[x]) + edge[i].len;
  91. }
  92. else {
  93. lenup[y] = std::max(lenup[x], len1[x]) + edge[i].len;
  94. }
  95. DFS_2(y, x);
  96. }
  97. return;
  98. }
  99.  
  100. int main() {
  101. int x, y;
  102. LL z, Sum = ;
  103. double ans = ;
  104. scanf("%d", &n);
  105. for(int i = ; i <= n; i++) {
  106. scanf("%d%d%lld", &x, &y, &z);
  107. add(x, y, z);
  108. add(y, x, z);
  109. ans += z;
  110. }
  111. Df(, );
  112.  
  113. for(int i = ; i <= tc; i++) {
  114. fr[cir[i]] = cir[i];
  115. DFS_1(cir[i], , (i == tc ? : i + ));
  116. DFS_2(cir[i], );
  117. cir[tc + i] = cir[i];
  118. }
  119. for(int i = ; i <= tc; i++) {
  120. Sum += dis[i];
  121. dis[tc + i] = dis[i];
  122. }
  123. for(int i = ; i <= tc * ; i++) {
  124. sum[i] = sum[i - ] + dis[i];
  125. }
  126.  
  127. LL dt = ;
  128. head = ;
  129. tail = ;
  130. for(int i = ; i <= tc * ; i++) {
  131. // DP
  132. while(head <= tail && sum[i] - sum[p[head]] > Sum - (sum[i] - sum[p[head]])) {
  133. head++;
  134. }
  135. dt += dis[i];
  136. if(head <= tail) {
  137. Long[cir[i]] = std::max(Long[cir[i]], p2[head] + dt);
  138. }
  139. while(head <= tail && len1[cir[i]] - dt >= p2[tail]) {
  140. tail--;
  141. }
  142. p[++tail] = i;
  143. p2[tail] = len1[cir[i]] - dt;
  144. }
  145. head = ;
  146. tail = ;
  147. dt = ;
  148. for(int i = tc * ; i >= ; i--) {
  149. while(head <= tail && sum[p[head]] - sum[i] > Sum - (sum[p[head]] - sum[i])) {
  150. head++;
  151. }
  152. dt += dis[i + ];
  153. if(head <= tail) {
  154. Long[cir[i]] = std::max(Long[cir[i]], p2[head] + dt);
  155. }
  156. while(head <= tail && len1[cir[i]] - dt >= p2[tail]) {
  157. tail--;
  158. }
  159. p[++tail] = i;
  160. p2[tail] = len1[cir[i]] - dt;
  161. }
  162. // -------------------------------------------------------------------------------------------------------
  163. head = ;
  164. tail = ;
  165. dt = ;
  166. dis[tc * + ] = dis[];
  167. for(int i = ; i <= tc * ; i++) {
  168. // DP
  169. while(head <= tail && sum[i] - sum[p[head]] > Sum - (sum[i] - sum[p[head]] + dis[i + ])) {
  170. head++;
  171. }
  172. dt += dis[i];
  173. if(head <= tail) {
  174. Long_l[cir[i]] = std::max(Long_l[cir[i]], p2[head] + dt);
  175. }
  176. while(head <= tail && len1[cir[i]] - dt >= p2[tail]) {
  177. tail--;
  178. }
  179. p[++tail] = i;
  180. p2[tail] = len1[cir[i]] - dt;
  181. }
  182. head = ;
  183. tail = ;
  184. dt = ;
  185. for(int i = tc * ; i >= ; i--) {
  186. while(head <= tail && sum[p[head]] - sum[i] > Sum - (sum[p[head]] - sum[i - ])) {
  187. head++;
  188. }
  189. dt += dis[i + ];
  190. if(head <= tail) {
  191. Long_r[cir[i]] = std::max(Long_r[cir[i]], p2[head] + dt);
  192. }
  193. while(head <= tail && len1[cir[i]] - dt >= p2[tail]) {
  194. tail--;
  195. }
  196. p[++tail] = i;
  197. p2[tail] = len1[cir[i]] - dt;
  198. }
  199. //
  200. for(int i = ; i <= top; i += ) {
  201. int x = edge[i].v, y = edge[i ^ ].v;
  202. LL a, b;
  203. if(is_cir[x] && is_cir[y]) {
  204. if(nex[y] == x) {
  205. std::swap(x, y);
  206. }
  207. a = std::max(Long_l[x], len1[x]);
  208. b = std::max(Long_r[y], len1[y]);
  209. }
  210. else {
  211. if(d[x] > d[y]) {
  212. std::swap(x, y);
  213. }
  214. a = len1[y];
  215. b = std::max(lenup[y] - edge[i].len, d[x] + Long[fr[x]]);
  216. }
  217. if(a < b) {
  218. std::swap(a, b);
  219. }
  220. if(a >= edge[i].len + b) {
  221. ans = std::min(ans, (double)a);
  222. }
  223. else {
  224. ans = std::min(ans, (a + b + edge[i].len) / 2.0);
  225. }
  226. }
  227.  
  228. printf("%.1f", ans);
  229. return ;
  230. }

AC代码

洛谷P1399 快餐店的更多相关文章

  1. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  2. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  3. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  4. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

  5. 洛谷P1710 地铁涨价

    P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交  讨论  题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...

  6. 洛谷P1371 NOI元丹

    P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交  讨论  题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...

  7. 洛谷P1538迎春舞会之数字舞蹈

    题目背景 HNSDFZ的同学们为了庆祝春节,准备排练一场舞会. 题目描述 在越来越讲究合作的时代,人们注意的更多的不是个人物的舞姿,而是集体的排列. 为了配合每年的倒计时,同学们决定排出——“数字舞蹈 ...

  8. 洛谷八月月赛Round1凄惨记

    个人背景: 上午9:30放学,然后因为学校举办读书工程跟同学去书城选书,中午回来开始打比赛,下午又回老家,中间抽出一点时间调代码,回家已经8:50了 也许是7月月赛时“连蒙带骗”AK的太幸运然而因同学 ...

  9. 洛谷 P1379 八数码难题 Label:判重&&bfs

    特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...

随机推荐

  1. Spring boot 将配置文件属性注入到一个bean中

    现在要做的就是将如下配置文件中的内容注入到一个bean 名为Properties中. Redis.properties配置文件中的内容如下: Properties java bean中代码如下,注意注 ...

  2. vue.js 添加 fastclick的支持

    fastclick:处理移动端click事件300毫秒延迟 1.兼容性 iOS 3及更高版本的移动Safari iOS 5及更高版本的Chrome Android上的Chrome(ICS) Opera ...

  3. lombok标签之@Data @AllArgsConstructor @@NoArgsConstructor -如何去除get,set方法。@Data注解和如何使用,lombok

    在代码中我们可以只加上标签@Data 而不用get,set方法: val : 和 scala 中 val 同名, 可以在运行时确定类型; @NonNull : 注解在参数上, 如果该类参数为 null ...

  4. 老男孩python学习自修第八天【函数式编程】

    1.可变参数,将传参自动汇总成列表 2.可变参数,将参数自动汇总成字典 实战如下: #!/usr/bin/env python # _*_ coding:UTF-8 _*_ def show(*arg ...

  5. Java HashMap的put操作(Java1.6)

    https://www.cnblogs.com/skywang12345/p/3310835.html // 存储数据的Entry数组,长度是2的幂. // HashMap是采用拉链法实现的,每一个E ...

  6. Atcoder Beginner Contest 121 D - XOR World(区间异或和)

    题目链接:https://atcoder.jp/contests/abc121/tasks/abc121_d 题目很裸(Atcoder好像都比较裸 就给一个区间求异或和 n到1e12 肯定不能O(n) ...

  7. vue的 v-for 循环中图片加载路径问题

    先看一下产品需求,如下图所示, 产品要求图片和它的名称一一对应,本来是非常简单的需求,后台直接返回图片路径和名称,前台直接读取就可以了,但是我们没有存储图片的服务器,再加上是一个实验性的需求,图片需要 ...

  8. poj-2513(字典树+欧拉通路)

    题意:给你n个火柴棍,每个火柴棍头和尾两种颜色,问你是否存在能够把这些火柴棍摆成一行的情况,两个相连的火柴棍的颜色需要一样: 解题思路:最初的思路是用map标记颜色,然后把每种颜色看作点,每根火柴棍看 ...

  9. Maven添加Web.xml的方法

    当创建maven工厂时没有web.xml文件1.点击你的项目名称,进入到Myeclipse的-- Project Facets上,2.点击Dynamic Web Module 和下面的Java,将两个 ...

  10. BZOJ4514[Sdoi2016]数字配对——最大费用最大流

    题目描述 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci ...