树上的路径 BZOJ 3784
树上的路径
【问题描述】
【输入格式】
【样例输入】
5 10
1 2 1
1 3 2
2 4 3
2 5 4
【样例输出】
7
7
6
5
4
4
3
3
2
1
【数据范围】
N<=50000,M<=Min(300000,n*(n-1) /2 )
题解:
考虑将点分治时访问的点的顺序作为一个序列
每个位置都有其对应的区间(指向这个位置所在重心树访问的前面所有子树,那么这就代表了这个位置对应的点出发经过这个重心的所有路径)
那么原问题转化为了BZOJ 2006 超级钢琴的问题
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf = ;
const int logn = ;
const int logs = ;
const int maxn = 5e4 + ;
const int maxm = maxn << ;
const int maxs = maxn * logn + ;
inline void Scan(int &x)
{
char c;
bool o = false;
while(!isdigit(c = getchar())) o = (c != '-') ? o : true;
x = c - '';
while(isdigit(c = getchar())) x = x * + c - '';
if(o) x = -x;
}
int tot, nex[maxm], ver[maxm], fir[maxn], val[maxm];
inline void Ins(int x, int y, int z)
{
nex[++tot] = fir[x];
fir[x] = tot;
ver[tot] = y;
val[tot] = z;
}
int sum, root;
int size[maxn], heavy[maxn];
bool vis[maxn];
void Getroot(int u, int f)
{
heavy[u] = ;
size[u] = ;
for(int i = fir[u]; i; i = nex[i])
{
int v = ver[i];
if(v == f || vis[v]) continue;
Getroot(v, u);
size[u] += size[v];
heavy[u] = max(heavy[u], size[v]);
}
heavy[u] = max(heavy[u], sum - size[u]);
if(heavy[u] < heavy[root]) root = u;
}
struct couple
{
int l, r;
};
couple c[maxs];
int num, l, r;
int dis[maxn], len[maxs];
int big[logs][maxs];
void Getdis(int u, int f)
{
len[++num] = dis[u], big[][num] = num;
c[num] = (couple) {l, r};
for(int i = fir[u]; i; i = nex[i])
{
int v = ver[i];
if(v == f || vis[v]) continue;
dis[v] = dis[u] + val[i];
Getdis(v, u);
}
}
void Div(int u)
{
root = ;
Getroot(u, );
l = r = ++num;
len[num] = , big[][num] = num;
vis[root] = true;
for(int i = fir[root]; i; i = nex[i])
{
int v = ver[i];
if(vis[v]) continue;
dis[v] = val[i];
Getdis(v, root);
r = num;
}
for(int i = fir[root]; i; i = nex[i])
{
int v = ver[i];
if(vis[v]) continue;
sum = size[v];
Div(v);
}
}
inline int Max(int a, int b)
{
return (len[a] > len[b]) ? a : b;
}
int bin[logs], lg[maxs];
inline void Rmq()
{
int lgn = log2(num);
bin[] = ;
for(int i = ; i <= lgn; ++i) bin[i] = bin[i - ] << , lg[bin[i]] = ;
for(int i = ; i <= num; ++i) lg[i] += lg[i - ];
for(int k = ; k <= lgn; ++k)
for(int i = ; i <= num; ++i)
{
if(i + bin[k] - > num) continue;
int j = i + bin[k - ];
big[k][i] = Max(big[k - ][i], big[k - ][j]);
}
}
inline int Query(int l, int r)
{
if(l > r) return -;
int len = lg[r - l + ];
return Max(big[len][l], big[len][r - bin[len] + ]);
}
int n, m;
struct interval
{
int l, r, a, b, v;
};
inline bool operator < (interval a, interval b)
{
return a.v < b.v;
}
priority_queue <interval> q;
int main()
{
Scan(n), Scan(m);
int a, b;
for(int i = ; i < n; ++i)
{
int c;
Scan(a), Scan(b), Scan(c);
Ins(a, b, c), Ins(b, a, c);
}
sum = n;
root = ;
heavy[] = inf;
Div();
Rmq();
int x;
for(int i = ; i <= num; ++i)
{
a = c[i].l, b = c[i].r;
if(a)
{
x = Query(a, b);
q.push((interval) {a, b, i, x, len[i] + len[x]});
}
}
int u, v;
interval s;
while(m--)
{
s = q.top(), q.pop();
u = Query(s.l, s.b - );
v = Query(s.b + , s.r);
if(u > ) q.push((interval) {s.l, s.b - , s.a, u, len[u] + len[s.a]});
if(v > ) q.push((interval) {s.b + , s.r, s.a, v, len[v] + len[s.a]});
printf("%d\n", s.v);
}
}
树上的路径 BZOJ 3784的更多相关文章
- bzoj 3784: 树上的路径 堆维护第k大
3784: 树上的路径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 88 Solved: 27[Submit][Status][Discuss] ...
- 【BZOJ-3784】树上的路径 点分治 + ST + 堆
3784: 树上的路径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 462 Solved: 153[Submit][Status][Discuss ...
- codevs 2756树上的路径
题意: 2756 树上的路径 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给出一棵树,求出最小的k,使得,且在树 ...
- 【BZOJ3784】树上的路径 点分治序+ST表
[BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...
- Codevs 2756 树上的路径
2756 树上的路径 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给出一棵树,求出最小的k,使得,且在树中存在 ...
- BZOJ 3784: 树上的路径
Description 问一棵树上前 \(k\) 大路径的边权. Sol 边分治. 非常感谢数据没有菊花图. 为了写写边分治试试然后就开了这道题. 边分治非常好想,选一条重边,分成两部分,然后分别求最 ...
- BZOJ.3784.树上的路径(点分治 贪心 堆)
BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...
- bzoj 3784: 树上的路径【点分治+st表+堆】
参考:https://www.cnblogs.com/CQzhangyu/p/7071477.html 神奇的点分治序(或者叫点剖?).就是把点分治扫过的点依次放进队列里,然后发现,对于每一棵树摊到序 ...
- BZOJ 3784: 树上的路径 点分治+二分+set
很容易想出二分这个思路,但是要想办法去掉一个 $log$. 没错,空间换时间. 双指针的部分错了好几次~ Code: #include <set> #include <queue&g ...
随机推荐
- JS节点操作(JS原生+JQuery)
JavaScript与JQuery节点操作 节点关系与类型 任何HTML元素,都有nodeType属性.值有1~12,常用的有: 1.元素节点 2.文本节点 8.注释节点 9.document节点 ...
- MySQL数据库---索引
索引的作用就是快速找出在一个列上用一特定值的行.如果没有索引,MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行. 索引的类型: 先写一个建表语句: CREATE TABLE `t ...
- Golang tcp转发 remoteAddr错误
Golang tcp 转发 第一版本 accept获取的Conn里的localAddr做为源地址,remoteAddr来做为目的地址 // tcpForward package main import ...
- Linux安装OpenCV
sudo apt-get update sudo apt-get install git git clone https://github.com/jayrambhia/Install-OpenCV ...
- Form和ModelForm组件
Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否 ...
- loadView、viewDidLoad及viewDidUnload的关系(转)
本文目录 一.loadView 二.viewDidLoad 三.viewDidUnload 四.三个方法的关系 标题中所说的3个方法,都是UIViewController的方法,跟UIViewCont ...
- UVA1589——xiangqi
开始碰到这个题时觉得太麻烦了直接跳过没做,现在放假了再次看这个题发现没有想象中那么麻烦,主要是题目理解要透彻,基本思路就是用结构体数组存下红方棋子,让黑将军每次移动一下,看移动后是否有一个红方棋子可以 ...
- Centos7重启网卡失败解决方法
service Network-Manager stop 执行命令解决,如果执行命令还是失败,则是配置文件内容的问题,检查配置文件
- Python之多线程与多进程(二)
多进程 上一章:Python多线程与多进程(一) 由于GIL的存在,Python的多线程并没有实现真正的并行.因此,一些问题使用threading模块并不能解决 不过Python为并行提供了一个替代方 ...
- php生成Exeple表demo
<?php require "./PHPExcel.php"; $dir=dirname(__FILE__); $objPHPExcel=new PHPExcel(); $o ...