bzoj4890[Tjoi2017]城市(树的半径)
4890: [Tjoi2017]城市
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 149 Solved: 91
[Submit][Status][Discuss]
Description
Input
输入数据的第一行为一个整数n,代表城市个数。
接下来的n - 1行分别代表了最初的n-1条公路情况。每一行都有三个整数u,v,d。u,v代表这条公路的两端城市标号,d代表这条公路的交通费用。
Output
Sample Input
5
1 2 1
2 3 2
3 4 3
4 5 4
Sample Output
HINT
对于30%的数据,1<=n<500
对于100%的数据,1<=n<=5000
1 <= u,v <= n,1<= d <= 2000
/*
要想删一条边再添一条边使一棵树中两点间最大距离最小
容易想到跟树的直径有关
N比较小,可以枚举要删那一条边。删掉(u,v)之后树就成了两个联通块。
如果树的直径没变,对答案没有影响。 可以求出联通块1,2的直径。
(所以可以只枚举删直径上的边,但我没有...)
那么问题就转化为在1,2联通块内分别找一个点使它到联通块内最远的点距离最近。
这个距离就是树的半径。然后把这两个点连起来即可。
如何维护半径?
求直径时需要求出每个点为起点的最长链和次长链
考虑距离它最远的那个点,在它的子树内还是子树外
子树内:最长链
子树外:dfs维护这个点子树外的最长链
如何维护一个点子树外的最长链?
当dfs到一个x时,对于x和他的父亲y,若x不在y的最长链内,那么ans[x](x到子树外最远距离)为max(y最长链+dis[x][y],ans[y]+dis[x][y])
否则ans[x]为max(y的次长链+dis[x][y],ans[y]+dis[x][y])
最后对每种情况答案取min即可。
*/
#include<bits/stdc++.h> #define N 5007
#define inf 0x3f3f3f3f using namespace std;
int n,m,ans,cnt,dis,res;
int head[N<<],mv[N],u[N],v[N],w[N];
int dp[N][];
bool vis[N];
struct edge{
int u,v,w,nxt;
}e[N<<]; inline void add(int u,int v,int w)
{
e[++cnt].v=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt;
} inline int read()
{
int x=,f=;char c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} void getd(int u)
{
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].v;
if(vis[v]) continue;
vis[v]=;getd(v);
if(dp[u][]<dp[v][]+e[i].w)
{
dp[u][]=dp[u][];mv[u]=v;
dp[u][]=dp[v][]+e[i].w;
}
else if(dp[u][]<dp[v][]+e[i].w)
dp[u][]=dp[v][]+e[i].w;
}dis=max(dis,dp[u][]+dp[u][]);
} void getr(int u,int from)
{
res=min(res,max(from,dp[u][]));
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].v;
if(!vis[v]) continue;
vis[v]=;
if(mv[u]==v)
getr(v,max(dp[u][]+e[i].w,from+e[i].w));
else
getr(v,max(dp[u][]+e[i].w,from+e[i].w)); }
} void clear()
{
memset(dp,,sizeof dp);
memset(mv,,sizeof mv);
memset(vis,,sizeof vis);
res=inf;dis=;
} int main()
{
n=read();
for(int i=;i<n;i++)
{
u[i]=read();v[i]=read();w[i]=read();
add(u[i],v[i],w[i]);add(v[i],u[i],w[i]);
}
int d1,d2,r1,r2;ans=res=inf;dis=;
for(int i=;i<n;i++)
{
vis[v[i]]=;getd(u[i]); d1=dis;
dis=;getd(v[i]); d2=dis;
//联通块1,2的直径
vis[v[i]]=;getr(u[i],); r1=res;
res=inf;getr(v[i],); r2=res;
//联通块1,2的半径
ans=min(ans,max(max(d1,d2),r1+r2+w[i]));
clear();
}
printf("%d\n",ans);
return ;
}
bzoj4890[Tjoi2017]城市(树的半径)的更多相关文章
- BZOJ4890 Tjoi2017城市
显然删掉的边肯定是直径上的边.考虑枚举删哪一条.然后考虑怎么连.显然新边应该满足其两端点在各自树中作为根能使树深度最小.只要线性求出这个东西就可以了,这与求树的重心的过程类似. #include< ...
- [BZOJ4890][TJOI2017]城市(DP)
题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收 ...
- BZOJ4890 [Tjoi2017]城市 【树形dp】
题目链接 BZOJ4890 题解 枚举断开哪一条边,然后对剩余的两棵树分别做一遍换根法树形dp 需要求出每个点到树中其它点距离的最大值\(f[i]\)和次大值\(g[i]\)[用以辅助换根计算最大值] ...
- [TJOI2017] 城市 (树的直径,贪心)
题目链接 Solution 这道题,调了我一晚上... 一直80分 >_<|| ... 考虑到几点: 分开任意一条边 \(u\) ,那么其肯定会断成两棵树. 肯定是分开直径上的边最优,否则 ...
- luogu P3761 [TJOI2017]城市 树的直径 bfs
LINK:城市 谢邀,学弟说的一道毒瘤题. 没有真正的省选题目毒瘤 或者说 写O(n)的做法确实毒瘤. 这里给一个花20min就写完的非常好写的暴力. 容易想到枚举哪条边删掉 删掉之后考虑在哪两个点上 ...
- 【BZOJ4890】[TJOI2017]城市(动态规划)
[BZOJ4890][TJOI2017]城市(动态规划) 题面 BZOJ 洛谷 题解 数据范围都这样了,显然可以暴力枚举断开哪条边. 然后求出两侧直径,暴力在直径上面找到一个点,使得其距离直径两端点的 ...
- [TJOI2017]城市(树的直径)
[TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达, ...
- 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市
P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...
- [TJOI2017]城市 【树的直径+暴力+优化】
Online Judge:Luogu P3761 Label:树的直径,暴力 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有n座城市,n-1条高速公路,保证了 ...
随机推荐
- Floyd算法实现总结
问题描述 给出图,求任意两点的最短距离 算法思路 定义n+1个矩阵矩阵A,和记录路径的矩阵path 依次求A0~An的值,最后的An即为最短路径矩阵 // int A[8][7][7],path[7] ...
- Leetcode 215.数组中的第k个最大元素
数组中的第k个最大元素 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 ...
- MySQL中间件之ProxySQL_读写分离/查询重写配置
MySQL中间件之ProxySQL_读写分离/查询重写配置 Posted on 2016-12-25 by mark blue, mark Leave a comment MySQL 1.闲扯几句 读 ...
- [luoguP1388] 算式(DP)
传送门 看这个n<=15本以为是个状压DP 还是too young 这个题最神奇的地方是加括号是根据贪心的策略. 发现只有在一连串的加号两边加上括号才是最优的(想一想,为什么?) f[i][j] ...
- intent使用Serializable传递对象
package com.pingyijinren.test; import android.content.Intent; import android.support.v7.app.AppCompa ...
- IOS7状态栏StatusBar官方标准适配方法
IOS7状态栏StatusBar官方标准适配方法 hello,大家好,ios7正式版已经发布,相信大家都在以各种方式来适配ios7. 如果你已经下载了xcode5,正准备使用,你会发现各种布局的改变. ...
- P1165 日志分析 洛谷
https://www.luogu.org/problem/show?pid=1165 题目描述 M 海运公司最近要对旗下仓库的货物进出情况进行统计.目前他们所拥有的唯一记录就是一个记录集装箱进出情况 ...
- 洛谷—— P3386 【模板】二分图匹配
P3386 [模板]二分图匹配(复习) 题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每 ...
- linux network name space
linux network namespace概念类似于网络中的 VRF (virtual routing and forwarding).但是,你不知道VRF的概念也没关系,下面我们通过一个简单的介 ...
- Codeforces Round #247 (Div. 2) B
B. Shower Line time limit per test 1 second memory limit per test 256 megabytes input standard input ...