洛谷题目链接:[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. 如何做好FAE工作及FAE职位发展

    此文较长,是作者对于半导体FAE职业的一些总结,码字不容易,耐心的阅读,欢迎点赞. 曾经认识一位做电源研发的工程师,转行在一家代理商做FAE,做了一年半以后,就提出了离职请求,他老板问他是什么原因,他 ...

  2. C语言特殊符号

    -> ->在C语言中称为间接引用运算符,是二目运算符,优先级同成员运算符“.”.用法:p->a,其中p是指向一个结构体的指针,a是这个结构体类型的一个成员.表达式p->a引用了 ...

  3. C#创建Window服务图解,安装、配置、以及C#操作Windows服务

    一.首先打开VS2013,创建Windows服务项目 二.创建完成后对"Service1.cs"重命名位"ServiceDemo":然后切换到代码视图,写个服务 ...

  4. C# .net 调用QQ邮箱

    public static void QQfs() { try { MailMessage mm = new MailMessage(); MailAddress Fromma = new MailA ...

  5. 3dContactPointAnnotationTool开发日志(六)

      一种可行的思路就是枚举一个模型的三角面片,然后判断三角形是否与另一个物体相交即可.为了让效果更好我想只渲染模型的线框.   在网上查了半天好像Unity里都没有自带的方便的渲染线框的方式,我又自己 ...

  6. 个人作业4 alpha阶段 个人总结

    一.个人总结 二.回答问题 三.再提问题 Q1:关于第三章过早优化 过早优化:既然软件是"软"的,那么它就有很大的可塑性,可以不断改进.放眼望去,一个复杂的软件似乎很多的模块都可以 ...

  7. HDU 2163 Palindromes

    http://acm.hdu.edu.cn/showproblem.php?pid=2163 Problem Description Write a program to determine whet ...

  8. Nautilus-Share-Message: Called "net usershare info" but it failed: Failed to

    See what nautilus processes are running : ps aux | grep nautilus Kill all nautilus processes you see ...

  9. java-实用的sql语句

    一.在数据库创建表格的SQL语句 1,创建一个link表格,包含属性:lid  主键,title 标题,  imgpath 图片地址 , url  网址  , info 说明,  isshow 显示1 ...

  10. div、span绑定内容改变事件

    内容改变事件onchange只适用于form表单标签(input.select.textarea) 当需要对div.span标签进行内容改变监听则无法适用,查阅了一些资料发现jquery有针对的方法, ...