BZOJ3124 [Sdoi2013]直径 【树的直径】
题目
小Q最近学习了一些图论知识。根据课本,有如下定义。树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度。如果一棵树有N个节点,可以证明其有且仅有N-1 条边。 路径:一棵树上,任意两个节点之间最多有一条简单路径。我们用 dis(a,b)
表示点a和点b的路径上各边长度之和。称dis(a,b)为a、b两个节点间的距离。
直径:一棵树上,最长的路径为树的直径。树的直径可能不是唯一的。
现在小Q想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。
输入格式
第一行包含一个整数N,表示节点数。
接下来N-1行,每行三个整数a, b, c ,表示点 a和点b之间有一条长度为c
的无向边。
输出格式
共两行。第一行一个整数,表示直径的长度。第二行一个整数,表示被所有
直径经过的边的数量。
输入样例
6
3 1 1000
1 4 10
4 2 100
4 5 50
4 6 100
输出样例
1110
2
提示
【样例说明】
直径共有两条,3 到2的路径和3到6的路径。这两条直径都经过边(3, 1)和边(1, 4)。
对于100%的测试数据:2≤N≤200000,所有点的编号都在1..N的范围内,
边的权值≤10^9。
题解
首先我们先求出树的直径,解决问题1
然后对于这条我们任意找出的直径,答案一定在这条直径上,因为其它直径对于这条直径来说,没有被访问到
我们就看看这条直径上还有那些直径经过
我们求出直径上每个点的外向树到这条直径的最远距离
如果存在一个点的最远距离 + 次远距离 = 直径长,那么答案是0
否则求出直径上每个点向左能延伸的最远距离及该距离下最近的拐点,向右也求出
记为ml,mr,拐点记为pre和post,直径长为L
如果\(ml + mr = L\),说明有一条直径经过区间\([pre,post]\),那么区间外的边一定不是答案
如此反复,我们得到若干个区间,排个序取公共部分就是答案
埋头乱码竟1A,,
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 200005,maxm = 400005,INF = 100000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int h[maxn],ne = 2;
struct EDGE{int to,nxt,w;}ed[maxm];
inline void build(int u,int v,int w){
ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],w}; h[v] = ne++;
}
int n,rt,fa[maxn],c[maxn],vis[maxn],tot;
LL d[maxn],sum[maxn],ansL;
void dfs1(int u){
if (d[u] > d[rt]) rt = u;
Redge(u) if ((to = ed[k].to) != fa[u]){
d[to] = d[u] + ed[k].w; fa[to] = u;
dfs1(to);
}
}
void solve1(){
dfs1(1);
d[rt] = 0; fa[rt] = 0;
dfs1(rt);
for (int i = rt; i; i = fa[i]){
c[++tot] = i;
sum[tot] = d[i];
vis[i] = true;
}
reverse(c + 1,c + 1 + tot);
reverse(sum + 1,sum + 1 + tot);
printf("%lld\n",ansL = d[rt]);
}
LL gmax,hmax,md[maxn],ml[maxn],mr[maxn];
int pre[maxn],post[maxn];
void dfs2(int u){
if (d[u] >= gmax){
hmax = gmax;
gmax = d[u];
}
else if (d[u] > hmax){
hmax = d[u];
}
vis[u] = true;
Redge(u) if (!vis[to = ed[k].to]){
d[to] = d[u] + ed[k].w;
dfs2(to);
}
}
struct inter{int l,r;}e[2 * maxn];
int cnt,tag[maxn];
inline bool operator <(const inter& a,const inter& b){
return a.l == b.l ? a.r < b.r : a.l < b.l;
}
void solve2(){
for (int i = 1; i <= tot; i++){
gmax = hmax = -INF; d[c[i]] = 0;
dfs2(c[i]);
md[i] = gmax;
if (gmax + hmax == ansL){
puts("0");
return;
}
}
ml[1] = md[1]; pre[1] = 1;
for (int i = 2; i <= tot; i++){
if (md[i] >= ml[i - 1] + sum[i] - sum[i - 1]){
pre[i] = i;
ml[i] = md[i];
}
else {
pre[i] = pre[i - 1];
ml[i] = ml[i - 1] + sum[i] - sum[i - 1];
}
}
mr[tot] = md[tot]; post[tot] = tot;
for (int i = tot - 1; i; i--){
if (md[i] >= mr[i + 1] + sum[i + 1] - sum[i]){
post[i] = i;
mr[i] = md[i];
}
else {
post[i] = post[i + 1];
mr[i] = mr[i + 1] + sum[i + 1] - sum[i];
}
}
for (int i = 1; i <= tot; i++){
if (pre[i] == post[i]) continue;
if (ml[i] + mr[i] == ansL){
e[++cnt] = (inter){1,pre[i]};
e[++cnt] = (inter){post[i],tot};
}
}
sort(e + 1,e + 1 + cnt);
int l = 0,r = -1;
for (int i = 1; i <= cnt; i++){
if (e[i].l > r + 1){
for (int j = l; j <= r; j++) tag[j] = true;
l = e[i].l;
r = e[i].r;
}
else r = max(r,e[i].r);
}
for (int j = l; j <= r; j++) tag[j] = true;
int ans = 0;
for (int i = 1; i <= tot; i++){
if (i != 1 && i != tot && !tag[i]){
ans++;
if (tag[i - 1]) ans++;
}
}
printf("%d\n",ans);
}
int main(){
n = read();
int a,b,w;
for (int i = 1; i < n; i++){
a = read(); b = read(); w = read();
build(a,b,w);
}
solve1();
solve2();
return 0;
}
BZOJ3124 [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]直径 树形dp two points
题目链接 bzoj3124: [Sdoi2013]直径 题解 发现所有直径都经过的边 一定在一条直径上,并且是连续的 在一条直径上找这段区间的两个就好了 代码 #include<map> ...
- bzoj千题计划134:bzoj3124: [Sdoi2013]直径
http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...
- 2018.11.05 bzoj3124: [Sdoi2013]直径(树形dp)
传送门 一道sbsbsb树形dpdpdp 第一问直接求树的直径. 考虑第二问问的边肯定在同一条直径上均是连续的. 因此我们将直径记下来. 然后对于直径上的每一个点,dpdpdp出以这个点为根的子树中不 ...
- SDOI2013直径(树的直径)
题目描述: 点这里 题目大意: 就是在一个树上找其直径的长度是多少,以及有多少条边满足所有的直径都经过该边. 题解: 首先,第一问很好求,两边dfs就行了,第一次从任一点找距它最远的点,再从这个点找距 ...
- poj2631 求树的直径裸题
题目链接:http://poj.org/problem?id=2631 题意:给出一棵树的两边结点以及权重,就这条路上的最长路. 思路:求实求树的直径. 这里给出树的直径的证明: 主要是利用了反证法: ...
- poj1985 Cow Marathon (求树的直径)
Cow Marathon Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 3195 Accepted: 1596 Case ...
随机推荐
- Struts2标签<s:checkboxlist>回显问题
Struts2 checkboxlist回显问题中,说明两种方式,第一种方式很普遍,第二种则是个人根据现有资源加上尝试得来的成果,第二种主要是为个人笔记(其中相关知识点不一一介绍). 一.普通方法: ...
- Sublime Text 3 使用小记
快捷键: [ // 代码对齐插件 { "keys": ["shift+alt+a"], "command": "alignment ...
- 分布式系统中的CAP原理和BASE理论
CAP是一致性(Consistency).可用性(Availability).分区容忍性(Partition tolerance)的缩写.CAP原理指的是这三个要素最多只能同时实现两点,不可能三者兼顾 ...
- 从零开发分布式数据库中间件 二、构建MyBatis的读写分离数据库中间件
在上一节 从零开发分布式数据库中间件 一.读写分离的数据库中间件 中,我们讲了如何通过ThreadLocal来指定每次访问的数据源,并通过jdbc的连接方式来切换数据源,那么这一节我们使用我们常用的数 ...
- 增加和减少mongodb复制集中的节点
MongoDB Replica Sets不仅提供高可用性的解决方案,同时也提供负载均衡的解决方案,增减 Replica Sets节点在实际应用中非常普通.例如,当应用的读压力暴增时,3台节点的环境已不 ...
- java 核心技术卷一笔记 6 .2接口 lambda 表达式 内部类
6.2 接口实例 6.2.1 接口与回调 在java.swing包中有一个Timer类,可以使用它在到达给定的时间间隔时发出通告,假如程序中有一个时钟,就可以请求每秒钟获得一个通告,以便更新时钟的表盘 ...
- Python学习日志9月13日
昨天的学习日志没有写,乱忙了一整天,政治电脑. 好奇心重,想要给电脑装上传说中LInux操作系统,各种小问题折腾到半夜,今天又折腾到晚上才真正的装上系统. 可是装上系统后又发现各种的不好用.虽然界面比 ...
- MINST手写数字识别(三)—— 使用antirectifier替换ReLU激活函数
这是一个来自官网的示例:https://github.com/keras-team/keras/blob/master/examples/antirectifier.py 与之前的MINST手写数字识 ...
- javascript中typeof、undefined 和 null
typeof 是运算符,注意不是函数,是运算符,其作用,是考察变量究竟是什么类型.或曰,是变量是否定义或是否初始化的照妖镜.返回值是字符串. undefined 表示一个对象没有被定义或者没有被初始化 ...
- Bootstrap历练实例:基本按钮组
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...