题目

小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]直径 【树的直径】的更多相关文章

  1. POJ 1985.Cow Marathon-树的直径-树的直径模板(BFS、DFS(vector存图)、DFS(前向星存图))

    Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7536   Accepted: 3559 Case ...

  2. [SDOI2013]直径 (树的直径,贪心)

    题目链接 Solution 我们直接找到一条直径 \(s\),起点为 \(begin\),终点为 \(end\). 从前往后遍历点 \(u\) ,若子树中最大的距离与 \(dis(u,begin)\) ...

  3. 树形DP 学习笔记(树形DP、树的直径、树的重心)

    前言:寒假讲过树形DP,这次再复习一下. -------------- 基本的树形DP 实现形式 树形DP的主要实现形式是$dfs$.这是因为树的特殊结构决定的——只有确定了儿子,才能决定父亲.划分阶 ...

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

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

  5. bzoj千题计划134:bzoj3124: [Sdoi2013]直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...

  6. 2018.11.05 bzoj3124: [Sdoi2013]直径(树形dp)

    传送门 一道sbsbsb树形dpdpdp 第一问直接求树的直径. 考虑第二问问的边肯定在同一条直径上均是连续的. 因此我们将直径记下来. 然后对于直径上的每一个点,dpdpdp出以这个点为根的子树中不 ...

  7. SDOI2013直径(树的直径)

    题目描述: 点这里 题目大意: 就是在一个树上找其直径的长度是多少,以及有多少条边满足所有的直径都经过该边. 题解: 首先,第一问很好求,两边dfs就行了,第一次从任一点找距它最远的点,再从这个点找距 ...

  8. poj2631 求树的直径裸题

    题目链接:http://poj.org/problem?id=2631 题意:给出一棵树的两边结点以及权重,就这条路上的最长路. 思路:求实求树的直径. 这里给出树的直径的证明: 主要是利用了反证法: ...

  9. poj1985 Cow Marathon (求树的直径)

    Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 3195   Accepted: 1596 Case ...

随机推荐

  1. uvm.sv——UVM之道

    文件: $UVM_HOME/src/uvm.sv 类: 无   `include "uvm_pkg.sv"   Thus spake the UVM master programm ...

  2. iOS  UDP 广播 AsyncSocket 用法

    因为业务需要,需要用广播发送一个字段,在iOS开发中,用到了AsynSocket. 1.定义一个属性,负责发送和接受数据 #define YX_Local_Host @"255.255.25 ...

  3. Selenium私房菜系列5 -- 第一个Selenium RC测试案例

    <Selenium简介>中讲过,Selenium RC支持多种语言编写测试案例,如:C#,Python.在工作中,我倾向于是用Python这类动态语言编写测试案例,因为这样的测试案例无需编 ...

  4. SQLite C/C++ 教程

    目录 1安装 2 C/C++ Interface APIs 3连接到数据库 4创建表 5插入操作 6更新操作 7删除操作 安装 在我们开始使用SQLite在C / C++程序,我们需要确保SQLite ...

  5. CocoaPods 安装使用

    CocoaPods是一个负责管理iOS项目中第三方开源代码的工具.CocoaPods项目的源码在Github上管理.该项目开始于2011年8月 12日,经过一年多的发展,现在已经超过1000次提交,并 ...

  6. Gym 100883J palprime(二分判断点在凸包里)

    题意:判断一堆小点有多少个在任意三个大点构成的三角形里面. 思路:其实就是判断点在不在凸包里面,判断的话可以使用二分来判断,就是判断该点在凸包的哪两个点和起点的连线之间. 代码: /** @xigua ...

  7. Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.Reason: Failed to determine a suitable driver class

    解决方案: @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) 作用://取消数据库配置 但是 在用到数据库的时候记 ...

  8. grep, egrep, fgrep - 打印匹配给定模式的行

    总览 SYNOPSIS grep [options] PATTERN [FILE...] grep [options] [-e PATTERN | -f FILE] [FILE...] 描述 DESC ...

  9. spark 省份次数统计实例

    //统计access.log文件里面IP地址对应的省份,并把结果存入到mysql package access1 import java.sql.DriverManager import org.ap ...

  10. pseudogene|鉴定功能基因|expressed se|quence tag

    基因 (鉴定DNA:可以直接利用DNA序列鉴别基因,但存在3个问题) 1.intron太长(使用用来连接的算法不可及) 2.因为通常功能基因的第一个oxen中有非编码区和启动子最后一个oxen中有终止 ...