SDOI2013直径(树的直径)
题目描述:
题目大意:
就是在一个树上找其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。
题解:
首先,第一问很好求,两边dfs就行了,第一次从任一点找距它最远的点,再从这个点找距它的最远点,后两个点就是树的直径的两个端点,证明就不赘述了,有兴趣可以自己证一证玩一玩。
那第二问怎么办呢?假设我们有这样一个图(如下)

如图所示,中间那根直的就是树的直径之一,旁边标红的也是树的直径。(图画的不好,感性理解)
我们要知道,树的直径是必定会有交叉的,可以画个图自己看一下。
所以就会有一个想法:首先找出一条直径的起点,向终点推,如果碰到交叉,就看这个交叉是否是直径,如果是,就把第一个直径收缩,再继续找。再从终点向起点收缩一遍。剩下的边就是题目中要求的了。
最后就是代码实现了,收缩的过程是真滴玄学。
代码如下:
#include<iostream>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define rint register int
#define M 200005
using namespace std;
inline int read()
{
int s=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){s=s*+ch-'';ch=getchar();}
return s*f;
}
inline ll max(ll a,ll b){return a>b?a:b;}
ll dis[M],maxx,s,t;
ll n,m,cnt,head[M],vis[M];
ll dep[M],father[M],l,r,ans,son[M];
struct edge
{
int to,nex,v;
}e[M<<];
inline void add(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].v=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
void dfs(int u,int fa)
{
for(rint i=head[u];i;i=e[i].nex)
{
int v=e[i].to;if(v==fa) continue;father[v]=u;
dis[v]=dis[u]+e[i].v;dfs(v,u);
}
}
void find(int u,int fa)
{
dep[u]=;ll maxn=;
for(rint i=head[u];i;i=e[i].nex)
{
int v=e[i].to;if(v==father[u] || vis[v]==) continue;
find(v,u);maxn=max(maxn,dep[v]+e[i].v);
}
dep[u]=maxn;
}
int main()
{
n=read();
for(rint i=;i<=n-;++i)
{
int x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
dfs(,);
for(rint i=;i<=n;++i)
{
if(dis[i]>maxx) maxx=dis[i],s=i;
dis[i]=;
}
dfs(s,);maxx=;
for(rint i=;i<=n;++i)
{
if(dis[i]>maxx) maxx=dis[i],t=i;
}
printf("%lld\n",maxx);
int l=t,r=s,now=t;
while(now!=s)
{
vis[now]=;
son[father[now]]=now;
now=father[now];
}
now=t;
while(now!=s)
{
dep[now]=;
find(now,);
if(dep[now]==maxx-dis[now]) l=now;
now=father[now];
}
now=s;
while(now)
{
find(now,);
if(dep[now]==dis[now]) r=now;
now=son[now];
}
while(l!=r && l)
{
l=father[l];
++ans;
}
printf("%lld\n",ans);
return ;
}
谢谢大家!
SDOI2013直径(树的直径)的更多相关文章
- POJ 1985.Cow Marathon-树的直径-树的直径模板(BFS、DFS(vector存图)、DFS(前向星存图))
Cow Marathon Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 7536 Accepted: 3559 Case ...
- [SDOI2013]直径 (树的直径,贪心)
题目链接 Solution 我们直接找到一条直径 \(s\),起点为 \(begin\),终点为 \(end\). 从前往后遍历点 \(u\) ,若子树中最大的距离与 \(dis(u,begin)\) ...
- 树形DP 学习笔记(树形DP、树的直径、树的重心)
前言:寒假讲过树形DP,这次再复习一下. -------------- 基本的树形DP 实现形式 树形DP的主要实现形式是$dfs$.这是因为树的特殊结构决定的——只有确定了儿子,才能决定父亲.划分阶 ...
- BZOJ3124 [Sdoi2013]直径 【树的直径】
题目 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一棵树上,任意两个节 ...
- poj2631 求树的直径裸题
题目链接:http://poj.org/problem?id=2631 题意:给出一棵树的两边结点以及权重,就这条路上的最长路. 思路:求实求树的直径. 这里给出树的直径的证明: 主要是利用了反证法: ...
- poj1985 Cow Marathon (求树的直径)
Cow Marathon Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 3195 Accepted: 1596 Case ...
- VIJOS1476旅游规划[树形DP 树的直径]
描述 W市的交通规划出现了重大问题,市政府下决心在全市的各大交通路口安排交通疏导员来疏导密集的车流.但由于人员不足,W市市长决定只在最需要安排人员的路口安放人员.具体说来,W市的交通网络十分简单,它包 ...
- poj2631 树的直径
设s-t是这棵树的直径,那么对于任意给予的一点,它能够到达的最远的点是s或者t. 这样我们可以通过2次bfs找到树的直径了. #include<cstdio> #include<qu ...
- 【BZOJ-1912】patrol巡逻 树的直径 + DFS(树形DP)
1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1034 Solved: 562[Submit][St ...
随机推荐
- iOS学习之自定义弹出UIPickerView或UIDatePicker(动画效果)
前面iOS学习之UIPickerView控件的简单使用 用到的UIPickerView弹出来是通过 textField.inputView = selectPicker; textField.in ...
- python's is&==区别
[python's is&==区别] 通常我们写: if foo is None: pass 这个写法与以下的写法有何区别呢? if foo == None: pass is当比较的是相同的对 ...
- Excel VBA入门(一)数据类型
与其它的编程语言一样,VBA也有它自己的数据类型.讲到数据类型,就离不开"变量"与"常量"这两个概念,变量与常量,都是用于保存数据的.顾名思义,"变量 ...
- Excel VBA 入门(零)
本教程所用系统环境: Windows 10 Excel 2013 1. 添加开发工具 打开Excel,依然找到"文件"->"选项"->"自 ...
- git服务器搭建问题
CentOS6.5本地搭建. 对于图形化的系统,可以联网,然后CTRL+ALT+F2可以切换到命令行,CTRL+ALT+F1可以切换回桌面图形化. 可以用SSH和FTP来连接服务器和传文件. (1 ...
- 【ZOJ 3228】Searching the String 【AC自动机】
题意 给出n个模式串和一个文本串,输出各个模式串在文本串中出现的次数.模式串有两种类型,0类型代表可以有重叠,1类型代表不能有重叠.模式串可能出现重复. 分析 算是AC自动机的模板题? 因为模式串可以 ...
- Nginx源码完全注释(4)ngx_queue.h / ngx_queue.c
队列头文件ngx_queue.h #include <ngx_config.h> #include <ngx_core.h> #ifndef _NGX_QUEUE_H_INCL ...
- git回滚到某个commit 上和 返回最新的版本git
1. 代码回退 首先你要用git log 查看你要回到的那个本版, 然后用 git reset --hard HEAD^ 回退到上个版本 git reset --hard commit_id 退到/进 ...
- 关于java是值传递还是引用传递
一.概念 实际上对这两种传递方式,知乎上有个回答说得很好: 值传递和引用传递,属于函数调用时参数的求值策略(Evaluation Strategy),这是对调用函数时,求值和传值的方式的描述,而非传递 ...
- g2o的使用
相关文献 1.论文 Grisetti, Giorgio, et al. “A tutorial on graph-based SLAM.” IEEE Intelligent Transportatio ...