传送门

题意

有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. JavaScript - 正则表达式解惑

    正则表达式手册: http://tool.oschina.net/uploads/apidocs/jquery/regexp.html 正则表达式测试地址: http://tool.chinaz.co ...

  2. ci中 chrome对favicon.ico请求,导致log报错 解决方法

    chrome浏览器会自动对favicon.ico进行请求,所以当没有为网站添加 favicon.ico 时会出现404的页面错误在实际开发过程中,CI框架 打开 ERROR log,会一直显示ERRO ...

  3. CSS属性中Display与Visibility的不同

    大多数人很容易将CSS属性display和visibility混淆,它们看似没有什么不同,其实它们的差别却是很大的.visibility属性用来确定元素是显示还是隐藏,这用visibility=&qu ...

  4. 混合minxins

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. jquery事件手冊

    方法 描写叙述 bind() 向匹配元素附加一个或很多其它事件处理器 blur() 触发.或将函数绑定到指定元素的 blur 事件 change() 触发.或将函数绑定到指定元素的 change 事件 ...

  6. VMWare 14 Workstation Pro 下载与安装

    1.双击安装运行 2.下一步 3.接受 下一步 4.自定义安装路径,下一步 5.下一步,取消勾选加入vmware客户体验 6.下一步 7.安装 8.安装中 9.完成 10.点击许可证安装 输入:FF3 ...

  7. mips-openwrt-linux-gcc test_usbsw.c -o usbsw 编译问题

      mips-openwrt-linux-gcc: warning: environment variable 'STAGING_DIR' not defined mips-openwrt-linux ...

  8. 使用GitLab CI + Capistrano部署CakePHP应用程序

    使用GitLab CI + Capistrano部署CakePHP应用程序 摘要:本文描述了如使用GitLab CI + Capistrano部署CakePHP应用程序. 目录 1. 问题2. 解决方 ...

  9. Django 之ORM操作

    1.什么是ORM? 全称关系对象映射Object Relational Mapping(简称ORM),是通过描述面向对象与数据库之间的对应的元数据,将对象持久化的更新到数据库中. 有了ORM,就不需要 ...

  10. ReactMotion Demo8 分析

    链接 首先通过spring函数Motion的style参数, 传入Motion Component, 计算style的过程: const style = lastPressed === i & ...