传送门

题意

有n个小镇,Bobo想要建造n-1条边,并且如果在u到v建边,那么花费是u到v的最短路长度(原图),问你最大的花费。

分析

比赛的时候没做出来,QAQ

我们首先要找到树的直径起点和终点,方法是

1.任意选一个点,dfs找到最长路的终点

2.从终点反向dfs,找到起点

然后枚举每个点,用倍增lca求出该点到起点与终点距离,取距离大的,注意直径本身会被访问两次,故一开始ans要减去最长路,时间复杂度O(nlogn)

代码

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std; #define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
#pragma comment(linker, "/STACK:102400000,102400000")
inline void read(int &x){x=0; char ch=getchar();while(ch<'0') ch=getchar();while(ch>='0'){x=x*10+ch-48; ch=getchar();}} int t,n,m;
int fa[100100],depth[100100],up[100100][20],vis[100100];
ll dis[100100],dis2[100100];
struct node
{
int to;
ll w;
node(int tt,ll ww):to(tt),w(ww){}
};
vector<node>edge[100100]; void dfs(int u,int pre,int dep)//第一次dfs,标出每个点的父亲,计算从该点到1的距离dus[i]
{
depth[u]=dep;//记录深度
fa[u]=pre;//记录父亲
int num=edge[u].size();
R(i,0,num)
{
int v=edge[u][i].to;
if(v!=pre)
{
dis[v]=dis[u]+edge[u][i].w;//更新距离
dfs(v,u,dep+1);
}
}
}
void dfs2(int x)//第二次遍历,从第一次dfs的最大距离点遍历
{
int num=edge[x].size();
vis[x]=1;//用vis记录该点是否被访问
R(i,0,num)
{
int v=edge[x][i].to;
if(!vis[v])
{
dis2[v]=dis2[x]+edge[x][i].w;//记录距离
dfs2(v);
}
}
}
void create()//构建倍增数组
{
mem(up,0);
F(i,1,n) up[i][0]=fa[i];
for(int j=1;j<20;++j)for(int i=1;i<=n;++i)
up[i][j]=up[up[i][j-1]][j-1];
}
int lca(int u,int v)//找到u和v的的最近公共祖先
{
if(depth[u]<depth[v]) swap(u,v);
int ret=depth[u]-depth[v];
R(i,0,20)if(ret&(1<<i)) u=up[u][i];//将u调整到与v同深度
if(u==v) return u;//同一侧,则返回
for(int i=19;i>=0;--i) if(up[u][i]!=up[v][i])//不同则让u和v向上跳,直到跳不了
{
u=up[u][i];
v=up[v][i];
}
return fa[u];
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int u,v;ll w;
F(i,0,n) edge[i].clear();
mem(fa,0);mem(depth,0);
mem(dis,0);mem(dis2,0);//注意dis和dis2的清空
for(int i=1;i<n;++i)
{
scanf("%d%d%I64d",&u,&v,&w);
edge[u].push_back(node(v,w));
edge[v].push_back(node(u,w));
}
dfs(1,0,0);
ll maxx=0;int End,Begin;
F(i,1,n) if(maxx<dis[i]) { maxx=dis[i];End=i; }//记录从1开始的最长路终点
create();
mem(vis,0);
dfs2(End);
maxx=0;
F(i,1,n) if(maxx<dis2[i]) { maxx=dis2[i];Begin=i; }//找到反向dfs最长路的点,那么Begin和End构成树的直径
ll ans=-maxx;//要遍历树的直径两次,故先减去一次
F(i,1,n)
{
ll ret1,ret2;
ret1=dis[i]+dis[Begin]-2*dis[lca(i,Begin)];
ret2=dis[i]+dis[End]-2*dis[lca(i,End)];
ans+=max(ret1,ret2);//去当前点到直径两端的最短路长度的最大值
}
printf("%I64d\n",ans);
}
return 0;
}

XTU1267:Highway(LCA+树的直径)的更多相关文章

  1. TZOJ 3481 Highway Construction(树的直径+最短路)

    描述 As head of the Accessible Commuting Movement (ACM), you've been lobbying the mayor to build a new ...

  2. XTOJ 1267:Highway(树的直径)***

    http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1267 题意:给出一棵树,每条树边有权值,现在要修建n-1条边,边的权值为边 ...

  3. 【CSP模拟赛】避难向导(倍增lca&树的直径)

    耐力OIer,一天7篇博客 题目描述 “特大新闻,特大新闻!全国爆发了一种极其可怕的病毒,已经开始在各个城市 中传播开来!全国陷入了巨大的危机!大量居民陷入恐慌,想要逃到其它城市以 避难!经调查显示, ...

  4. BZOJ 1776: [Usaco2010 Hol]cowpol 奶牛政坛 LCA + 树的直径

    Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) ...

  5. XTU 1267 - Highway - [树的直径][2017湘潭邀请赛H题(江苏省赛)]

    这道题可能有毒……总之一会儿能过一会儿不能过的,搞的我很心烦…… 依然是上次2017江苏省赛的题目,之前期末考试结束了之后有想补一下这道题,当时比较懵逼不知道怎么做……看了题解也不是很懂……就只好放弃 ...

  6. 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径

    51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...

  7. 【bzoj3362/3363/3364/3365】[Usaco2004 Feb]树上问题杂烩 并查集/树的直径/LCA/树的点分治

    题目描述 农夫约翰有N(2≤N≤40000)个农场,标号1到N,M(2≤M≤40000)条的不同的垂直或水平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地图一样, 图中农场用F ...

  8. [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树)

    [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树) 题面 给出一棵N个点的树,Q次询问一点编号在区间[l1,r1]内,另一点编号在区间[l2,r2]内的所有点对距离最大值.\ ...

  9. 树的直径,LCA复习笔记

    前言 复习笔记第6篇. 求直径的两种方法 树形DP: dfs(y); ans=max( ans,d[x]+d[y]+w[i] ); d[x]=max( d[x],d[y]+w[i] ); int di ...

随机推荐

  1. Linux和Windows设备驱动架构比较

    毕业后一直在学操作系统, 有时候觉得什么都懂了,有时候又觉得好像什么都不懂,但总体来说自认为对操作系统实现机制的了解比周围的人还是要多一些.去年曾花了几个星期的晚上时间断断续续翻译了这篇对Linux和 ...

  2. 移动Web开发实践

    移动设备的高速发展给用户带来了非常大的便利.用户使用Android.iPhone和其他移动设备非常easy接入互联网. 移动设备对网页的性能要求比較高.以下就说说Mobile Web开发的一些心得. ...

  3. (转载)display:inline、block、inline-block的区别

    display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...

  4. HBase运维基础--元数据逆向修复原理

    背景 鉴于上次一篇文章——“云HBase小组成功抢救某公司自建HBase集群,挽救30+T数据”的读者反馈,对HBase的逆向工程比较感兴趣,并咨询如何使用相应工具进行运维等等.总的来说,就是想更深层 ...

  5. To verify Hadoop releases using GPG

    To verify Hadoop releases using GPG http://hadoop.apache.org/releases.html To verify Hadoop releases ...

  6. java 相关博客

    Intellij Idea 创建Web项目入门(一) SpringMVC 和 MyBatis 学习笔记,搭配示例,主要讲解一些基础的概念.用法和配置 包含框架有:SpringMVC.MyBaits.A ...

  7. button在firefox 和 ie 下的问题

    最近做了一个关于数据库管理的项目,因为不用考虑ie9以下的兼容性,所以一股脑的写完啦,到测试的时候发现了一个bug IE和火狐下有个模块关闭按钮的hover没有反应,ie不行就算了,火狐怎么也不行?我 ...

  8. iOS 如何改变表视图分割线在iOS7中的默认偏移

    - (void)viewDidLoad { [super viewDidLoad]; self.automaticallyAdjustsScrollViewInsets = NO; if ([self ...

  9. get all sites under IIS

    https://stackoverflow.com/questions/2555668/how-to-programmatically-get-sites-list-and-virtual-dirs- ...

  10. YTU 2878: 结构体--学生信息排序

    2878: 结构体--学生信息排序 时间限制: 1 Sec  内存限制: 128 MB 提交: 297  解决: 148 题目描述 定义存放一个学生信息的结构体类型,学生信息包括:姓名,学号,性别,院 ...