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. JAVA基础补漏--继承

    子类的对象在创建时,首先调用父类的构造函数,再调用子类自己的构造函数. 子类的构造函数中,有一个默认的super(),为一个无参调用,这个不显示,但会被首先调用,所有才会有父类构造函数被调用的情况. ...

  2. spring security使用hibernate进行查询数据库验证

    前面查询数据库采用的都是jdbc方式,如果系统使用的是hibernate,该如何进行呢,下面就是实现步骤,关键还是实现自定义的UserDetailsService 项目结构如下: 使用hibernat ...

  3. MySql判断汉字、日期、数字的具体函数

    几个平常用的mysql函数,MySql判断汉字.日期.数字的具体函数分享给大家,具体内容如下 1.判断字符串是否为汉字 返回值:1-汉字 0-非汉字 ? 1 2 3 4 5 6 7 8 9 10 11 ...

  4. eclipse中的错误解决——The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

    看看我们遇到的问题 解决问题

  5. 换个思维,boot结合vue做后台管理

    可以添加,可以删除.动态的添加数据. 不用操作dom,只要操作json数据即可. <form class="form-horizontal addForm" id=" ...

  6. Pandas选项和自定义

    Pandas提供API来自定义其行为的某些方面,大多使用来显示. API由五个相关函数组成.它们分别是 - get_option() set_option() reset_option() descr ...

  7. Pandas索引和选择数据

    在本章中,我们将讨论如何切割和丢弃日期,并获取Pandas中大对象的子集. Python和NumPy索引运算符"[]"和属性运算符".". 可以在广泛的用例中快 ...

  8. angularjs地址栏传参

    1:路由定义参数 2.controller 3. 4.目标得到参数值

  9. 22个HTML5的初级技巧

    Web技术的发展速度太快了,如果你不与时俱进,就会被淘汰.因此,为了应对即将到来的HTML5,本文总结了22个HTML5的初级技巧,希望能对你进一步学习好HTML5会有所帮助. 1. 新的Doctyp ...

  10. Jexus部署Asp.Net Core项目

    在之前的我的博客项目中,我将.net Core发布到Cent OS 上,使用的Nginx代理以及Supervisor进程守护,看过我的博客的童鞋,也会发现,这种方式比较麻烦,光命令行就看的头大,总共部 ...