洛谷题目链接:[TJOI2017]城市

题目描述

从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作。这个地区一共有ri座城市,《-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收取一定的交通费用。小明对这个地区深入研究后,觉得这个地区的交通费用太贵。小明想彻底改造这个地区,但是由于上司给他的资源有限,因而小明现在只能对一条高速公路进行改造,改造的方式就是去掉一条高速公路,并且重新修建一条一样的高速公路(即交通费用一样),使得这个地区的两个城市之间的最大交通费用最小(即使得交通费用最大的两座城市之间的交通费用最小),并且保证修建完之后任意两座城市相互可达。如果你是小明,你怎么解决这个问题?

输入输出格式

输入格式:

输入数据的第一行为一个整数n,代表城市个数。

接下来的n - 1行分别代表了最初的n-1条公路情况。每一行都有三个整数u,v,d。u,v代表这条公路的两端城市标号,d代表这条公路的交通费用。

1 <= u,v <= n,1<= d <= 2000

输出格式:

输出数据仅有一行,一个整数,表示进行了最优的改造之后,该地区两城市 之间最大交通费用。

输入输出样例

输入样例#1:

5

1 2 1

2 3 2

3 4 3

4 5 4

输出样例#1:

7

说明

对于30%的数据,1<=n<500

对于100%的数据,1<=n<=5000


一句话题意: 给出一颗树,现在可以断开一条边并重新选择一个位置连接使得这张图仍然是一棵树.


题解: 因为在一棵树上断掉一条边之后,一定会成为两个连通块.那么再在这两个连通块中连一条边,两个连通块重新组成一棵树,那么这时树中的最长的距离就是新组成的直径.

那么新组成的直径该怎么计算呢?

显然我们可以分情况讨论:

  1. 断开一条边后形成的两个连通块中一条直径比较长,另一条直径比较短,将直径短的那颗树接到直径较长的树中后新树的直径仍然小于之前较长的直径.
  2. 两条直径差不多长,无论怎么接都会增加长度.此时我们需要它增加的长度尽量小,那么显然是要将两根直径的一半的位置接起来.此时直径可能不能恰好分成平均的两段,我们需要取折半后的较长段的最小值作为半径(想一下为什么).

那么这样就将所有的合并情况都讨论出来了,我们只需要枚举每一条边断开然后取合并后的最小值就可以了.

#include<bits/stdc++.h>
using namespace std;
const int N = 5000+5;
const int inf = 2147483647; int n, ecnt = 1, last[N], ans = inf, f[N], fa[N], q[N], cnt, dist[N], pre[N], dep[N];
int len[2], L[2], R[2]; struct edge{
int from, nex, to, w;
}e[N*2]; void add(int x, int y, int z){
e[++ecnt].to = y, e[ecnt].w = z, e[ecnt].from = x, e[ecnt].nex = last[x], last[x] = ecnt;
} void dfs(int x, int las, int deep, int k){
dep[x] = deep, fa[x] = las;
for(int to, i=last[x];i;i=e[i].nex){
to = e[i].to; if(to == las) continue;
dfs(to, x, deep+1, k);
if(len[k] < f[x]+f[to]+e[i].w) len[k] = f[x]+f[to]+e[i].w, L[k] = pre[x], R[k] = pre[to];
if(f[x] < f[to]+e[i].w) f[x] = f[to]+e[i].w, pre[x] = pre[to];
}
} void get_dis(int x, int lca){
if(x == lca){ q[++cnt] = x; return; }
get_dis(fa[x], lca), q[++cnt] = x;
} int get(int x, int y){
cnt = 0 ; int lca, a = x, b = y, mn = inf;
if(dep[a] < dep[b]) swap(a, b);
while(dep[a] > dep[b]) a = fa[a];
if(a == b) lca = a;
else { while(a != b) a = fa[a], b = fa[b]; lca = a; }
while(x != lca) q[++cnt] = x, x = fa[x]; get_dis(y, lca);
for(int i=2;i<=cnt;i++)
for(int j=last[q[i]];j;j=e[j].nex)
if(e[j].to == q[i-1]) dist[q[i]] = dist[q[i-1]]+e[j].w;
for(int i=1;i<=cnt;i++) mn = min(mn, max(dist[q[i]], dist[q[cnt]]-dist[q[i]]));
return mn;
} void solve(int x, int y, int w){
memset(dist, 0, sizeof(dist)), L[0] = L[1] = R[0] = R[1] = 0;
memset(f, 0, sizeof(f)), len[0] = len[1] = 0;
for(int i=1;i<=n;i++) pre[i] = i;
dfs(x, y, 1, 0), dfs(y, x, 1, 1);
ans = min(ans, max(get(L[0], R[0])+get(L[1], R[1])+w, max(len[0], len[1])));
} int main(){
ios::sync_with_stdio(false);
int x, y, z; cin >> n;
for(int i=1; i<n; i++) cin >> x >> y >> z, add(x, y, z), add(y, x, z);
for(int i=2; i<=ecnt; i+=2) solve(e[i].from, e[i].to, e[i].w);
cout << ans << endl;
return 0;
}

[洛谷P3761] [TJOI2017]城市的更多相关文章

  1. 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市

    P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...

  2. [洛谷P3763] [TJOI2017]DNA

    洛谷题目链接:[TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其 ...

  3. 【经典DP】洛谷 P2782 友好城市

    嘤嘤嘤,昨天两个文化课老师在上奥赛时招呼我(亲切交流),今天又要写工作报告,没时间写题解,希望今天能补上 友好城市 题目://洛谷那粘来的题面竟然能把格式粘过来 题目描述 有一条横贯东西的大河,河有笔 ...

  4. 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】

    题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...

  5. 洛谷P3763 [Tjoi2017]DNA 【后缀数组】

    题目链接 洛谷P3763 题解 后缀数组裸题 在BZOJ被卡常到哭QAQ #include<algorithm> #include<iostream> #include< ...

  6. 洛谷P2782 友好城市 DP

    やはり まだあしたということは嘘でしょう.ぜんぶ忘れた( ´・ヮ・`) 所以今天就贴一道水题吧 原题>>https://www.luogu.org/problem/show?pid=278 ...

  7. 洛谷P2782 友好城市

    题目描述 有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市.北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同.没对友好城市都向政府申请在河上开辟一条直线航 ...

  8. 洛谷P3760 - [TJOI2017]异或和

    Portal Description 给出一个\(n(n\leq10^5)\)的序列\(\{a_n\}(\Sigma a_i\leq10^6)\),求该数列所有连续和的异或和. Solution 线段 ...

  9. 洛谷P3759 - [TJOI2017]不勤劳的图书管理员

    Portal Description 给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\l ...

随机推荐

  1. 【备忘】mysql常用操作汇总

    1.增删改查 // 插入一条数据 insert into tableName values('liu','bei') // 删除一条数据 delete from tableName where las ...

  2. Phpcms V9导航循环下拉菜单的调用技巧

    这个方法基于PC V9官方模版中的调用方法,然后利用后台的“Phpcms V9菜单是否显示设置”控制菜单是否显示出来. 先看看最后的效果: 调用方法: <div id="navbar& ...

  3. 冲刺ing-1

    冲刺一 1.第一天的工作分配: 姓名 任务分工 吴伟华(队长) 布置团队任务,发表汇总博客及第一次冲刺博客 蔺皓雯 讨论任务分配 杨池宇 讨论任务分配 鲁婧楠 讨论任务分配 曾茜 讨论任务分配 蔡晨旸 ...

  4. 你代码写得这么丑,一定是因为你长得不好看----panboo第一篇博客

    一.个人介绍 我叫潘博,软嵌162,学号1613072055. 以“panboo”名称混迹于各大开源IT论坛与博客. 除了编程,我的最大爱好是篮球与健身,热衷于各种IT技术与运动. 我做过的软件项目有 ...

  5. SQL 跨库查询

    使用SQL查询数据,不仅能查询当前库的数据,还可以跨数据库,甚至跨服务器查询. 下面给大家介绍一下跨服务器查询的步骤(以SQL Server为例): 1,建立数据库链接 EXEC sp_addlink ...

  6. seaj和requirejs模块化的简单案例

    如今,webpack.gulp等构件工具流行,有人说seajs.requirejs等纯前端的模块化工具已经被淘汰了,我不这么认为,毕竟纯前端领域想要实现模块化就官方来讲,还是有一段路要走的.也因此纯前 ...

  7. Jenkins系列-Jenkins忘记密码的修复方法

    找回 admin 用户的密码后,可以登录系统修改其他用户的密码. 1. Jenkins 目录结构 Jenkins 没有使用数据库,所有的信息都保存在 JENKINS_HOME 目录下的文件中.其中 J ...

  8. 操作 使用XML的方法

    XmlHelper是一个工具类 public static class XMLHelper { /// <summary> /// XML的编码方式,默认是UTF-8 /// </s ...

  9. Python 开篇及第一个Python程序

    本节内容 python 简单介绍 python 2.x 或者python 3.x python 安装 第一个python程序 一.python简单介绍 python的创始人为吉多.范罗苏姆(Guido ...

  10. 廖雪峰老师Python教程读后笔记

    廖老师网站:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000 花几天时间看了廖老师的 ...