对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。

Solution

有点意思

先随便求一条直径(两次DFS即可),不妨设为 \(s,t\),我们知道要求的这些边一定都在这条路径上,不妨将它看作一条线(用DFS + STACK把它提取出来),其中 \(s\) 叫左边, \(t\) 叫右边

我们现在就要在这条线上借出一段区间

考虑如何求它的右端点,以 \(s\) 为根跑 DFS,算出每个点子树的最长路径以及条数

从 \(t\) 往左扫,如果碰到某条边不是必须经过的边(可以根据 \(u,v\) 的最长路条数关系判断),就把它记下来

那么最后一次被记下来的边的左端点就是目标区间的右端点

左端点同理即可

#include <bits/stdc++.h>
using namespace std; #define int long long
const int N = 200005; vector <pair<int,int> > g[N];
int n,x[N],y[N],top; namespace sol1 {
int vis[N],dis[N],s,t,len;
void dfs(int p) {
vis[p]=1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first, w=g[p][i].second;
if(vis[q]==0) {
dis[q]=dis[p]+w;
dfs(q);
}
}
}
void solve() {
int tmp=0;
dfs(1);
for(int i=1;i<=n;i++) {
if(dis[tmp]<dis[i]) tmp=i;
}
s=tmp;
memset(vis,0,sizeof vis);
memset(dis,0,sizeof dis);
dfs(s);
for(int i=1;i<=n;i++) {
if(dis[tmp]<dis[i]) tmp=i;
}
t=tmp;
len=dis[tmp];
}
} namespace sol2 {
int vis[N],s,t;
bool dfs(int p) {
vis[p]=1;
if(p==s) return 1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first, w=g[p][i].second;
if(vis[q]==0) {
int tmp = dfs(q);
if(tmp) {
x[++top]=q;
y[top]=w;
return 1;
}
}
}
}
void solve(int _s,int _t ){
s=_s; t=_t;
dfs(t);
x[++top]=t;
}
} namespace sol3 {
int vis[N],f[N],h[N];
void dfs(int p) {
vis[p]=1;
h[p]=1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first, w=g[p][i].second;
if(vis[q]==0) {
dfs(q);
if(f[p]<f[q]+w) {
f[p]=f[q]+w;
h[p]=0;
}
if(f[p]==f[q]+w) h[p]+=h[q];
}
}
}
int solve(int s) {
dfs(s);
int ans=top;
//for(int i=1;i<=top;i++) cout<<h[x[i]]<<" ";
//cout<<endl;
for(int i=top-1;i;--i) {
if(h[x[i]]!=h[x[i+1]]) ans=i;
}
return ans;
}
} namespace sol4 {
int vis[N],f[N],h[N];
void dfs(int p) {
vis[p]=1;
h[p]=1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first, w=g[p][i].second;
if(vis[q]==0) {
dfs(q);
if(f[p]<f[q]+w) {
f[p]=f[q]+w;
h[p]=0;
}
if(f[p]==f[q]+w) h[p]+=h[q];
}
}
}
int solve(int s) {
dfs(s);
int ans=1;
//for(int i=1;i<=top;i++) cout<<h[x[i]]<<" ";
//cout<<endl;
for(int i=2;i<=top;i++) {
if(h[x[i]]!=h[x[i-1]]) ans=i;
}
return ans;
}
} signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<n;i++) {
int t1,t2,t3;
cin>>t1>>t2>>t3;
g[t1].push_back(make_pair(t2,t3));
g[t2].push_back(make_pair(t1,t3));
}
sol1::solve();
int s=sol1::s, t=sol1::t;
sol2::solve(s,t);
int ans1=sol3::solve(s);
int ans2=sol4::solve(t);
cout<<sol1::len<<endl<<ans1-ans2<<endl;
}

[SDOI2013] 直径 - 树形dp的更多相关文章

  1. bzoj3124: [Sdoi2013]直径 树形dp two points

    题目链接 bzoj3124: [Sdoi2013]直径 题解 发现所有直径都经过的边 一定在一条直径上,并且是连续的 在一条直径上找这段区间的两个就好了 代码 #include<map> ...

  2. 【BZOJ3124】[Sdoi2013]直径 树形DP(不用结论)

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

  3. BZOJ3124: [Sdoi2013]直径 (树形DP)

    题意:给一颗树 第一问求直径 第二问求有多少条边是所有直径都含有的 题解:求直径就不说了 解第二问需要自己摸索出一些性质 任意记录一条直径后 跑这条直径的每一个点  如果以这个点不经过直径能到达最远的 ...

  4. 2014 Super Training #9 E Destroy --树的直径+树形DP

    原题: ZOJ 3684 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3684 题意: 给你一棵树,树的根是树的中心(到其 ...

  5. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  6. [10.12模拟赛] 老大 (二分/树的直径/树形dp)

    [10.12模拟赛] 老大 题目描述 因为 OB 今年拿下 4 块金牌,学校赞助扩建劳模办公室为劳模办公室群,为了体现 OI 的特色,办公室群被设计成了树形(n 个点 n − 1 条边的无向连通图), ...

  7. Codeforces 633F 树的直径/树形DP

    题意:有两个小孩玩游戏,每个小孩可以选择一个起始点,并且下一个选择的点必须和自己选择的上一个点相邻,问两个选的点权和的最大值是多少? 思路:首先这个问题可以转化为求树上两不相交路径的点权和的最大值,对 ...

  8. HDU4514 湫湫系列故事——设计风景线 ——树的直径/树形dp+判环

    中文题面,给出一个图,问能不能成环,如果可以就输出YES.否则输出该树的直径. 这里的判环我们用路径压缩的并查集就能很快的判断出来,可以在输入的同时进行判断.这题重点就是求树的直径. 树直径的性质可以 ...

  9. 51nod"省选"模测 A 树的双直径(树形dp)

    题意 题目链接 Sol 比赛结束后才调出来..不多说啥了,就是因为自己菜. 裸的up-down dp,维护一下一个点上下的直径就行,一开始还想了个假的思路写了半天.. 转移都在代码注释里 毒瘤题目卡空 ...

随机推荐

  1. jvm 内存结构

    jvm 内存结构 graph TB A(jvm)-->E(类加载器系统) A-->B(运行时数据区) A-->D(本地库接口) A-->C(执行引擎) B-->虚拟机栈 ...

  2. 嗅探、DNS劫持配合CS钓鱼

    本章节讲述的是嗅探和DNS劫持的利用 嗅探:同一个局域网下,原本应该丢弃的包,被保留下来,即使不开双向欺骗 Driftnet工具:Driftnet监视网络流量,抓取网络流量中的JPEG和GIF图像.这 ...

  3. Linux如何定位文件在磁盘的物理位置

    我在学习研究Linux内核结构的时候,思考过一个问题:Linux如何定位文件在磁盘的物理位置每个文件都有一个inode,inode在内核代码中的数据结构如下: 1 struct ext4_inode ...

  4. #《Essential C++》读书笔记# 第二章 面向过程的编程风格

    基础知识 函数必须先被声明,然后才能被调用(被使用).函数的声明让编译器得以检查后续出现的使用方式是否正确--是否有足够的参数.参数类型是否正确,等等.函数声明不必提供函数体,但必须指明返回类型.函数 ...

  5. MySQL基础(7) | 触发器

    MySQL基础(7) | 触发器 基本语法 创建 CREATE TRIGGER trigger_name trigger_time trigger_event ON table_name FOR EA ...

  6. cf949C

    题意简述:有n个点,每一个点都有一个权值,然后有m个条件,每一个条件是a[x]!=a[y],让选择最少的点且至少选择1个,然后让这个点的权值+1,使得条件仍满足 所有数对k取模 题解:如果a[x]+1 ...

  7. IIS WEB站点设置

    IIS安装 打开控制面板 -> 程序 -> 打开或关闭Windows功能 ,在弹出得对话框中选择“Internet信息服务”复选框.我这里是Windows server 2019 ,界面有 ...

  8. 离线安装PostgreSQL11.6

    因为客户最近有一台CentOS7的虚拟机,但是没有联网,需要安装离线安装PostgreSQL 1.首先去官网下载离线安装包 https://www.postgresql.org/download/ 说 ...

  9. W25Q64BV(FLASH)(SPI)中文手册

    64兆位串行SPI FLASH存储器 1.常规介绍 W25Q64BV(64兆位)串行FLASH存储器为一个空间大小,引脚,功耗限制的系统提供解决方案.25Q系列的灵活性和性能良好超越了普通的串行FLA ...

  10. Qt实践-基于C++的UI设计基础

    学习网址:http://c.biancheng.net/view/1824.html 我的代码: 头文件qwdlgmanual.h: #ifndef QWDLGMANUAL_H #define QWD ...