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. day1 python判断输入的密码是否正确

    _username = 'leon' _password = 'zyl' username = input("username:") password = input(" ...

  2. 一个linux命令(6/13):traceroute命令

    通过traceroute 我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径.当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能会不 ...

  3. c++中指针作为函数参数的详细理解

    在C语言中,函数的参数不仅可以是整数.小数.字符等具体的数据,还可以是指向它们的指针.用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着 ...

  4. NGINX的IO模型详解

    普及: 用户空间与内核空间: 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的 ...

  5. windows技巧--优雅的设置环境变量,其实只是为了节约几秒宝贵的时间

    优雅的设置windows环境变量 环境变量的作用 将应用程序设置在环境变量以后,可以直接在cmd里面或者运行窗口中执行程序 分类 系统环境变量 对系统中所有用户有效,修改过后要重启生效 用户环境变量 ...

  6. CPU、内存通俗概念

    在计算机的组成结构中,有一个很重要的部分,就是存储器.存储器是用来存储程序和数据的部件,对于计算机来说,有了存储器,才有记忆功能,才能保证正常工作.存储器的种类很多,按其用途可分为主存储器和辅助存储器 ...

  7. Spring Cloud 之Spring-Security

    对于Spring-Security首先要明白这么几点: 1.什么是SpringSecurityurity2.SpringSecurity应用场景3.SpringBoot整合Security4.Secu ...

  8. nginx官网下载&百度云分享

    官网下载的链接: nginx官网下载地址:http://nginx.org/download/ 百度云分享 链接:https://pan.baidu.com/s/16m6zrFSkYCJtX0rD2Y ...

  9. Ubuntu 1210怎么获得root权限登录

    Ubuntu 12.10 怎么用Root 登录?以下是Ubuntu 12.10 启用Root 登录的方法吗,希望对大家有些帮助吧! 方法如下: 1.先设定一个 Root 密码 sudo passwd ...

  10. C-RAN

    无线接入网(RAN)是移动运营商赖以生存的重要资产.传统的无线接入网具有以下特点: 1. 每一个基站连接若干个固定数量的扇区天线,并覆盖小片区域,每个基站只能处理本小区收发信号: 2. 系统的容量是干 ...