bzoj 3784
第三道点分治。
首先找到黄学长的题解,他叫我参考XXX的题解,但已经没有了,然后找到另一个博客的简略题解,没看懂,最后看了一个晚上黄学长代码,写出来然后,写暴力都拍了小数据,但居然超时,。。。。然后改了一下存图方式,还是T,读入优化,还是T,最后把BFS找重心改成DFS找重心后才过的(因为DFS只遍历一遍,但BFS要多遍历几遍)。
————————————————————以上是废话————————————————————————
题目:给定一个边带权的无根树,求长度排名为前m的路径的长度。
首先,肯定不能求出所有路径来排序,因为n很大。但我们要求前m大的路径,容易想到,我们先求出极大路径,求出最大,删掉它,然后再加上新产生的极大路径,但我们怎么定义“极大路径”呢,是长度不能再延伸的路径吗,可以发现这样选择,求新产生的极大路径会出现问题。
那这道题是怎么做的呢?在点分治时,每一个重心会对应很多棵子树,先对当前重心代表的那一棵树进行一次DFS,幷保存每个点的DFS序,以及DFS序中每个位置对应点到当前重心的距离,并且我们为每个点保存一个DFS序的区间,该区间包含根和包含它的子树的左边的子树(不包含它所在的子树),这样元素(lf,rg,x)代表dfs序上第x个点与区间[lf,rg]上代表的点的路径,即它代表一些路径而不是一条。并且可以证明每一条路径属于且仅属于其中一个元素。
每个元素代表的路径中存在最长的路径,以该路径的长度为关键字将元素放进堆中,每次找到后,将那个元素分成两个。。。。。。。
。。。。。。。。。。
/**************************************************************
Problem: 3784
User: idy002
Language: C++
Result: Accepted
Time:6940 ms
Memory:208820 kb
****************************************************************/ #include <cstdio>
#include <cctype>
#include <vector>
#include <queue>
#define max(a,b) ((a)>(b)?(a):(b))
#define N 50010
#define S 2000010
using namespace std; void gn( int &a ) {
char ch;
ch = getchar();
while( ch<''||ch>'' ) ch=getchar();
a = ;
while( ''<=ch&&ch<='' ) {
a = a*+ch-'';
ch = getchar();
}
} int n, m;
int head[N], dest[N+N], wght[N+N], next[N+N], ntot;
int vis[N], dis[N], siz[N], bac[N], fat[N], tot_siz, cur_root;
int qdis[S], qlf[S], qrg[S], clf, crg, ind;
int stm[S][], bin[], log[N];
int qu[N], bg, ed; struct Paths {
int lf, rg, mx, cur;
Paths( int lf, int rg, int mx, int cur ):lf(lf),rg(rg),mx(mx),cur(cur) {}
bool operator<( const Paths & b ) const {
return qdis[mx]+qdis[cur] < qdis[b.mx]+qdis[b.cur];
}
};
priority_queue<Paths> pq; void insert( int u, int v, int w ) {
ntot++;
next[ntot] = head[u];
wght[ntot] = w;
dest[ntot] = v;
head[u] = ntot;
}
void dfs_dis( int u ) {
ind++;
qdis[ind] = dis[u];
qlf[ind] = clf;
qrg[ind] = crg;
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t], w=wght[t];
if( vis[v] || v==fat[u] ) continue;
dis[v] = dis[u]+w;
fat[v] = u;
dfs_dis( v );
}
} void dfs_root( int u ) {
siz[u] = ;
bac[u] = ;
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( vis[v] || v==fat[u] ) continue;
fat[v] = u;
dfs_root( v );
siz[u] += siz[v];
if( siz[v]>bac[u] ) bac[u]=siz[v];
}
if( bac[u]<tot_siz-siz[u] ) bac[u] = tot_siz-siz[u];
if( bac[cur_root]>bac[u] ) cur_root=u;
}
void build_vdcp( int rt ) {
tot_siz = siz[rt];
cur_root = ;
fat[rt] = rt;
dfs_root( rt );
rt = cur_root;
/* find the core of the block that not cross the vertex of visited */
/*
qu[bg=ed=1] = rt;
fat[rt] = rt;
siz[rt] = bac[rt] = 0;
while( ed>=bg ) {
int u=qu[bg++];
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( vis[v] || v==fat[u] ) continue;
qu[++ed] = v;
fat[v] = u;
siz[u] = bac[u] = 0;
}
}
for( int i=ed; i>=1; i-- ) {
int u=qu[i];
int p=fat[u];
siz[u]++;
siz[p] += siz[u];
if( bac[p]<siz[u] ) bac[p]=siz[u];
}
for( int i=ed; i>=1; i-- ) {
int u=qu[i];
if( bac[u]<siz[rt]-siz[u] ) bac[u]=siz[rt]-siz[u];
}
for( int i=ed; i>=1; i-- ) {
int u=qu[i];
if( bac[rt]>bac[u] ) rt=u;
}
*/
/* get the info of cur core */
ind++;
qdis[ind] = ;
qlf[ind] = qrg[ind] = ;
clf = crg = ind;
vis[rt] = true;
for( int t=head[rt]; t; t=next[t] ) {
int u=dest[t], w=wght[t];
if( vis[u] ) continue;
fat[u] = rt;
dis[u] = w;
fat[u] = u;
dfs_dis( u );
crg = ind;
}
for( int t=head[rt]; t; t=next[t] ) {
int u=dest[t];
if( vis[u] ) continue;
build_vdcp( u );
}
}
void build_stable() {
bin[] = ;
for( int i=; i<; i++ ) bin[i]=bin[i-]<<;
log[] = -;
for( int i=; i<=n; i++ ) log[i]=log[i>>]+;
for( int i=; i<=ind; i++ ) stm[i][] = i;
for( int p=; p<=log[n]; p++ )
for( int i=; i<=ind-bin[p]+; i++ ) {
int a = stm[i][p-];
int b = stm[i+bin[p-]][p-];
stm[i][p] = qdis[a]>qdis[b] ? a : b;
}
}
int rmq( int lf, int rg ) {
int len = rg-lf+;
int p = log[len];
int a = stm[lf][p];
int b = stm[rg-bin[p]+][p];
return qdis[a]>qdis[b] ? a : b;
}
int main() {
gn(n), gn(m);
for( int i=,u,v,w; i<n; i++ ) {
gn(u), gn(v), gn(w);
insert( u, v, w );
insert( v, u, w );
}
bac[] = n, siz[] = n;
build_vdcp( );
build_stable();
for( int i=; i<=ind; i++ )
if( qlf[i] ) pq.push( Paths(qlf[i],qrg[i],rmq(qlf[i],qrg[i]),i) );
for( int i=; i<=m; i++ ) {
Paths pth = pq.top();
pq.pop();
printf( "%d\n", qdis[pth.mx]+qdis[pth.cur] );
if( pth.lf<=pth.mx- ) pq.push( Paths(pth.lf,pth.mx-,rmq(pth.lf,pth.mx-),pth.cur) );
if( pth.rg>=pth.mx+ ) pq.push( Paths(pth.mx+,pth.rg,rmq(pth.mx+,pth.rg),pth.cur) );
}
}
bzoj 3784的更多相关文章
- BZOJ 3784: 树上的路径
Description 问一棵树上前 \(k\) 大路径的边权. Sol 边分治. 非常感谢数据没有菊花图. 为了写写边分治试试然后就开了这道题. 边分治非常好想,选一条重边,分成两部分,然后分别求最 ...
- bzoj 3784: 树上的路径 堆维护第k大
3784: 树上的路径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 88 Solved: 27[Submit][Status][Discuss] ...
- BZOJ.3784.树上的路径(点分治 贪心 堆)
BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...
- 树上的路径 BZOJ 3784
树上的路径 [问题描述] 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a<b.将这n*(n-1)/2个距 ...
- bzoj 3784: 树上的路径【点分治+st表+堆】
参考:https://www.cnblogs.com/CQzhangyu/p/7071477.html 神奇的点分治序(或者叫点剖?).就是把点分治扫过的点依次放进队列里,然后发现,对于每一棵树摊到序 ...
- BZOJ 3784: 树上的路径 点分治+二分+set
很容易想出二分这个思路,但是要想办法去掉一个 $log$. 没错,空间换时间. 双指针的部分错了好几次~ Code: #include <set> #include <queue&g ...
- 洛谷 3784(bzoj 4913) [SDOI2017]遗忘的集合——多项式求ln+MTT
题目:https://www.luogu.org/problemnew/show/P3784 https://www.lydsy.com/JudgeOnline/problem.php?id=4913 ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
随机推荐
- scrapy爬虫框架介绍
一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Scrapy的用途十分广泛,可 ...
- 使用maven打包项目遇到错误: http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
今天在使用maven打包项目时遇到一个错误: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin ...
- Balanced and stabilized quicksort method
The improved Quicksort method of the present invention utilizes two pointers initialized at opposite ...
- Linux 用户态与内核态的交互【转载】
Linux 用户态与内核态的交互 在 Linux 2.4 版以后版本的内核中,几乎全部的中断过程与用户态进程的通信都是使用 netlink 套接字实现的,例如iprote2网络管理工具,它与内核的交 ...
- linux系统cpu使用100%的命令
for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)`; do dd if=/dev/zero of=/d ...
- WireShark出现The NPF driver isn't running的问题
昨天开始尝试装上了wireshark网络监视软件,可是今天打开去总是出现“The NPF driver isn't running.You may have trouble capturing or ...
- Windows内核执行体对象管理器的操作过程与分析
我之前写过一个有关于对象管理的读书笔记.但是这篇文章与前面的不同,这是我个人对对象管理器到底是什么的一个分析,而且也是直接对WRK代码进行的阅读. 执行体对象即我们通常所言的内核对象,我们知道Wind ...
- Java学习(final、static关键词)
final关键词 概念:final的意思为最终,不可变.final是个修饰符,它可以用来修饰类,类的成员,以及局部变量.不能修饰构造方法. 特点: 1.final修饰的类不可以被继承,但可以继承别的类 ...
- yii2联表查询
我们用实例来说明这一部分 表结构 现在有客户表.订单表.图书表.作者表, 客户表Customer (id customer_name) 订单表Order (id order_ ...
- Codeforces Round #491 (Div. 2) E - Bus Number + 反思
E - Bus Number 最近感觉打CF各种车祸.....感觉要反思一下, 上次读错题,这次想当然地以为18!肯定暴了longlong 而没有去实践, 这个题我看到就感觉是枚举每个数字的个数,但是 ...