[SDOI2013] 直径 - 树形dp
对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。
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的更多相关文章
- bzoj3124: [Sdoi2013]直径 树形dp two points
题目链接 bzoj3124: [Sdoi2013]直径 题解 发现所有直径都经过的边 一定在一条直径上,并且是连续的 在一条直径上找这段区间的两个就好了 代码 #include<map> ...
- 【BZOJ3124】[Sdoi2013]直径 树形DP(不用结论)
[BZOJ3124][Sdoi2013]直径 Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节 ...
- BZOJ3124: [Sdoi2013]直径 (树形DP)
题意:给一颗树 第一问求直径 第二问求有多少条边是所有直径都含有的 题解:求直径就不说了 解第二问需要自己摸索出一些性质 任意记录一条直径后 跑这条直径的每一个点 如果以这个点不经过直径能到达最远的 ...
- 2014 Super Training #9 E Destroy --树的直径+树形DP
原题: ZOJ 3684 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3684 题意: 给你一棵树,树的根是树的中心(到其 ...
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- [10.12模拟赛] 老大 (二分/树的直径/树形dp)
[10.12模拟赛] 老大 题目描述 因为 OB 今年拿下 4 块金牌,学校赞助扩建劳模办公室为劳模办公室群,为了体现 OI 的特色,办公室群被设计成了树形(n 个点 n − 1 条边的无向连通图), ...
- Codeforces 633F 树的直径/树形DP
题意:有两个小孩玩游戏,每个小孩可以选择一个起始点,并且下一个选择的点必须和自己选择的上一个点相邻,问两个选的点权和的最大值是多少? 思路:首先这个问题可以转化为求树上两不相交路径的点权和的最大值,对 ...
- HDU4514 湫湫系列故事——设计风景线 ——树的直径/树形dp+判环
中文题面,给出一个图,问能不能成环,如果可以就输出YES.否则输出该树的直径. 这里的判环我们用路径压缩的并查集就能很快的判断出来,可以在输入的同时进行判断.这题重点就是求树的直径. 树直径的性质可以 ...
- 51nod"省选"模测 A 树的双直径(树形dp)
题意 题目链接 Sol 比赛结束后才调出来..不多说啥了,就是因为自己菜. 裸的up-down dp,维护一下一个点上下的直径就行,一开始还想了个假的思路写了半天.. 转移都在代码注释里 毒瘤题目卡空 ...
随机推荐
- C++ 实现string转BYTE
用于将形如"0x1A"的string转成BYTE类型 代码如下, 有问题欢迎指出 bool str2byte(const std::string &str, BYTE &a ...
- Orleans[NET Core 3.1] 学习笔记(四)( 2 )获取Grain的方式
简介 在这一节,我们将介绍如何在Silo和Client中获取Grain及调用Grain Grain获取方式 从Grain内部获取: //根据特定的Key值创建或获取指定的Grain IStudent ...
- JS淘宝小广告
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...
- oracle数据泵导入导出部分用户
问题描述:需要将140服务器中的tbomnew实例下的部分用户导入到118服务器下的tbompx实例中,本次导入导出的两个数据库均为19C 部分用户名:CORE,MSTDATA,BOMMGMT,CFG ...
- MySQL 8 用户定义函数
MySQL Server可以通过创建或者加载UDFs(User-Defined Functions)来扩展服务器功能. 通过CREATE FUNCTION语句加载 UDF,比如: CREATE FUN ...
- 小程序上拉触底&下拉加载
data: { pageNo: 1,//当前页 pageSize: 10,//每页条数 count:'',//总条数 orderList: [], }, onLoad: function () { v ...
- linux命令——find
简介:find是Linux系统中的常用命令(应用程序)之一.它是用来在指定目录层次结构(指定目录的子目录以及子目录的子目录)中查找符合指定条件的文件和目录 一:语法结构 find [directory ...
- 虚拟机安装_1_wincc_matriton
1,安装虚拟机: 选择:win7专业版64位ISO. 2,安装office2016 3,激活系统和OFFICE 4,安装winccV7.4 4.1 安装WINDOWS组件 MSMQ 4.1.1 安装I ...
- [MongoDB]MongoDB的ObjectId组成
一.ObjectId的组成首先通过终端命令行,向mongodb的collection中插入一条不带“_id”的记录.然后,通过查询刚插入的数据,发现自动生成了一个objectId“5e4fa350b6 ...
- 「JOI 2017 Final」绳
题意 loj 做法 首先我们观察到最后能折起来的充要条件是: 只有两个颜色,除首尾外,所有颜色块内的数量为偶数 因为为偶数,我们进一步推论: 所有颜色块起始位置奇偶性相同 然后因为增与减都会有相同花费 ...