Written with StackEdit.

Description

小\(Q\)最近学习了一些图论知识。根据课本,有如下定义。

  • 树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度。如果一棵树有\(N\)个节点,可以证明其有且仅有\(N-1\) 条边。
  • 路径:一棵树上,任意两个节点之间最多有一条简单路径。我们用 \(dis(a,b)\) 表示点\(a\)和点b的路径上各边长度之和。称\(dis(a,b)\)为\(a,b\)两个节点间的距离。
  • 直径:一棵树上,最长的路径为树的直径。树的直径可能不是唯一的。

现在小\(Q\)想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。

Input

第一行包含一个整数\(N\),表示节点数。

接下来\(N-1\)行,每行三个整数\(a, b, c\) ,表示点\(a\)和点\(b\)之间有一条长度为\(c\) 的无向边。

Output

共两行。第一行一个整数,表示直径的长度。第二行一个整数,表示被所有

直径经过的边的数量。

Sample Input

6

3 1 1000

1 4 10

4 2 100

4 5 50

4 6 100

Sample Output

1110

2

【样例说明】

直径共有两条,\(3\) 到\(2\)的路径和\(3\)到\(6\)的路径。这两条直径都经过边\((3, 1\))和边\((1, 4\))。

HINT

对于\(100\%\)的测试数据:\(2≤N≤2*10^5\),所有点的编号都在\(1..N\)的范围内, 边的权值\(≤10^9\)。

Solution

  • 第一问显然,两次\(dfs\)即可.
  • 关于第二问,各个最远点的\(LCA\)一定是在所有直径上的.
  • 所以两次\(dfs\)时记录所有的最远点,求出它们的\(LCA\)(熟练剖腹),两个\(LCA\)的深度差即为答案(可以感性理解一下).
#include<bits/stdc++.h>
using namespace std;
typedef long long LoveLive;
inline int read()
{
int out=0,fh=1;
char jp=getchar();
while ((jp>'9'||jp<'0')&&jp!='-')
jp=getchar();
if (jp=='-')
{
fh=-1;
jp=getchar();
}
while (jp>='0'&&jp<='9')
{
out=out*10+jp-'0';
jp=getchar();
}
return out*fh;
}
const int MAXN=2e5+10;
int n;
int cnt=0,head[MAXN];
int nx[MAXN<<1],to[MAXN<<1],val[MAXN<<1];
LoveLive dis[MAXN];
int dep[MAXN],siz[MAXN],top[MAXN],Fa[MAXN],sons[MAXN];
inline void add(int u,int v,int w)
{
++cnt;
nx[cnt]=head[u];
to[cnt]=v;
val[cnt]=w;
head[u]=cnt;
}
void dfs1(int u,int fa)
{
Fa[u]=fa;
siz[u]=1;
for(int i=head[u];i;i=nx[i])
{
int v=to[i];
if(v==fa)
continue;
dep[v]=dep[u]+1;
dis[v]=dis[u]+val[i];
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[sons[u]])
sons[u]=v;
}
}
void dfs2(int u,int tp,int fa)
{
top[u]=tp;
if(!sons[u])
return;
dfs2(sons[u],tp,u);
for(int i=head[u];i;i=nx[i])
{
int v=to[i];
if(v==fa || v==sons[u])
continue;
dfs2(v,v,u);
}
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
x=Fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
void init(int rt)
{
memset(sons,0,sizeof sons);
dep[rt]=1;
dis[rt]=0;
}
vector<int> G;
int main()
{
n=read();
for(int i=1;i<n;++i)
{
int u=read(),v=read(),w=read();
add(u,v,w);
add(v,u,w);
}
init(1);
dfs1(1,0);
dfs2(1,1,0);
LoveLive ans=0;
for(int i=1;i<=n;++i)
{
if(dis[i]>ans)
G.clear(),ans=dis[i];
if(ans==dis[i])
G.push_back(i);
}
int now=G[0];
int tot=G.size();
for(int i=1;i<tot;++i)
now=LCA(now,G[i]);
int lca1=now;
int rt=G[0];
ans=0;
init(rt);
dfs1(rt,0);
dfs2(rt,rt,0);
G.clear();
for(int i=1;i<=n;++i)
{
if(dis[i]>ans)
G.clear(),ans=dis[i];
if(ans==dis[i])
G.push_back(i);
}
printf("%lld\n",ans);
now=G[0];
tot=G.size();
for(int i=1;i<tot;++i)
now=LCA(now,G[i]);
int lca2=now;
printf("%d\n",abs(dep[lca1]-dep[lca2]));
return 0;
}

bzoj 3124 直径的更多相关文章

  1. Bzoj 3124: [Sdoi2013]直径 题解

    3124: [Sdoi2013]直径 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1222  Solved: 580[Submit][Status] ...

  2. bzoj 3124: [Sdoi2013]直径

    #include<cstdio> #include<iostream> #define M 400009 #define ll long long using namespac ...

  3. bzoj 3124 [Sdoi2013]直径(dfs)

    Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一 ...

  4. SDOI2013 R1 Day1

    目录 2018.3.22 Test 总结 T1 BZOJ.3122.[SDOI2013]随机数生成器(BSGS 等比数列) T2 BZOJ.3123.[SDOI2013]森林(主席树 启发式合并) T ...

  5. bzoj千题计划134:bzoj3124: [Sdoi2013]直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...

  6. 3124: [Sdoi2013]直径

    3124: [Sdoi2013]直径 https://www.lydsy.com/JudgeOnline/problem.php?id=3124 分析: 所有直径都经过的边,一定都是连续的一段.(画个 ...

  7. BZOJ 2282 & 树的直径

    SDOI2011的Dayx第2题 题意: 在树中找到一条权值和不超过S的链(为什么是链呢,因为题目中提到“使得路径的两端都是城市”,如果不是链那不就不止两端了吗——怎么这么机智的感觉...),使得不在 ...

  8. bzoj 2282 [Sdoi2011]消防(树的直径,二分)

    Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个国家 ...

  9. bzoj 1912 巡逻(树直径)

    Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Ou ...

随机推荐

  1. JavaScript创建类的三种方式

    //第一种 创建类方法. // 用方法模拟 构造函数. function classobj() { this.name = 'xiaoming'; } classobj.text = 'text'; ...

  2. Keepalived + Mysql 主主复制高可用

    环境 系统:Centos 7.4 x64 服务:Mariadb 5.5 .Keepalived 1.3.5.6  结构 主1:192.168.1.108 主2:192.168.1.109 VIP:19 ...

  3. C++二阶构造函数

    转自:http://blog.51cto.com/9291927/1896411 一.构造函数的问题 构造函数存在问题: A.构造函数只提供自动初始化成员变量的机会 B.不能保证初始化逻辑一定成功,如 ...

  4. Spring Boot 中配置切换

    步骤一:切换需求 有时候在本地测试是使用8080端口(默认端口),可是上线时使用的比如是9090端口(不常用的,以防被黑). 此时就可以通过多配置文件实现多配置支持与灵活切换. 步骤二:多配置文件 3 ...

  5. 使用node-inspector调试NodeJS代码

    使用node-inspector调试NodeJS代码 任何一门完备的语言技术栈都少不了健壮的调试工具,对于NodeJS平台同样如此,笔者研究了几种调试NodeJS代码的方式,通过对比,还是觉得node ...

  6. 多线程-模拟阻塞queue队列

    前阵子学习了多线程,现在进行总结一下,模拟队列. 分析问题: (1)首先需要一个容器存放元素,这里用linkedList队列. (2)每次像容器中添加或删除元素的时候需要计数,所以这里需要一个计数器, ...

  7. 通过案例说明struts2的工作流程

    本文主要是通过一个例子来说明Struts2的一个工作流程. 首先定义一个登录页面login.jsp: [java] view plaincopy <%@ page language=" ...

  8. ubantu中让g++支持c++11的办法

    g++ main.cpp -std=c++11 -o a 其中: main.cpp是要编译的源文件 a是编译后的文件名 注意-std=c++11不要写成-std=c11

  9. 报错org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [bean.xml]

    报这种错的原因基本上是applicationContext.xml文件中bean配置错误,错误如下: org.springframework.beans.factory.BeanCreationExc ...

  10. C# 运行时替换方法(需要unsafe编译)

    /* https://stackoverflow.com/questions/7299097/dynamically-replace-the-contents-of-a-c-sharp-method ...