[bzoj3784]树上的路径
来源:互联网 发布:淘宝网购物女装连衣裙夏装 编辑:程序博客网 时间:2024/04/27 08:16
题目大意
给出一颗树,边有边权,输出点对距离前K大。
点剖
我们先思考如果不是树是序列该怎么做。
显然先按照权值从大到小排序,然后扔进堆中n个点对(i,1),对于点对(i,j)其权值是i到j的距离。
每次从堆中取一个,然后把第二维加1再丢进去(当然要求丢进去的点对合法)
那么这道题点剖以后,对于每一个分治中心得到的序列也从小到大排序,然后丢点对进去。
一个点对的合法性指:
1、点对(i,j)满足
2、i与j是同一个分治中心。
3、i与j不属于分治中心的同一颗子树内。
#include<cstdio>#include<algorithm>#include<set>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=50000+10;struct dong{ int x,y,cnt,data; friend bool operator <(dong a,dong b){ return a.data>b.data; }};multiset<dong> s;dong zlt;int belong[maxn][20],d[maxn][20],g[maxn][20],b[maxn][20],num[20];int h[maxn],go[maxn*2],dis[maxn*2],next[maxn*2],a[maxn],size[maxn];bool bz[maxn];int i,j,k,l,t,n,m,tot,top,ans,wdc;void add(int x,int y,int z){ go[++tot]=y; dis[tot]=z; next[tot]=h[x]; h[x]=tot;}void dfs(int x,int y){ int t=h[x]; a[++top]=x; size[x]=1; while (t){ if (!bz[go[t]]&&go[t]!=y){ dfs(go[t],x); size[x]+=size[go[t]]; } t=next[t]; }}void dg(int x,int y,int cnt){ int t=h[x]; while (t){ if (!bz[go[t]]&&go[t]!=y){ d[go[t]][cnt]=d[x][cnt]+dis[t]; belong[go[t]][cnt]=belong[x][cnt]; dg(go[t],x,cnt); } t=next[t]; }}bool cmp(int x,int y){ return d[x][wdc]>d[y][wdc];}void solve(int x,int cnt){ top=0; dfs(x,0); int i,j=x,k=0,t; while (1){ t=h[j]; while (t){ if (!bz[go[t]]&&go[t]!=k&&size[go[t]]>top/2){ k=j; j=go[t]; break; } t=next[t]; } if (!t) break; } t=h[j]; while (t){ if (!bz[go[t]]){ belong[go[t]][cnt]=go[t]; d[go[t]][cnt]=dis[t]; dg(go[t],j,cnt); } t=next[t]; } fo(i,1,top) g[a[i]][cnt]=j; wdc=cnt; sort(a+1,a+top+1,cmp); fo(i,1,top){ zlt.x=i+num[cnt]; zlt.y=1+num[cnt]; zlt.cnt=cnt; zlt.data=d[a[i]][cnt]+d[a[1]][cnt]; s.insert(zlt); } fo(i,num[cnt]+1,num[cnt]+top) b[i][cnt]=a[i-num[cnt]]; num[cnt]+=top; bz[j]=1; t=h[j]; while (t){ if (!bz[go[t]]) solve(go[t],cnt+1); t=next[t]; }}int main(){ scanf("%d%d",&n,&m) ; fo(i,1,n-1){ scanf("%d%d%d",&j,&k,&l); add(j,k,l); add(k,j,l); } solve(1,0); while (m--){ while (1){ zlt=*s.begin(); s.erase(s.begin()); j=zlt.x;k=zlt.y;l=zlt.cnt;t=zlt.data; k++; if (k<=num[l]&&g[b[j][l]][l]==g[b[k][l]][l]){ zlt.data=d[b[j][l]][l]+d[b[k][l]][l]; zlt.y=k; s.insert(zlt); } k--; if (belong[b[j][l]][l]!=belong[b[k][l]][l]&&g[b[j][l]][l]==g[b[k][l]][l]&&b[j][l]<b[k][l]){ ans=t; break; } } printf("%d\n",ans); }}
0 0
- [bzoj3784]树上的路径
- 【bzoj3784】树上的路径
- [bzoj3784][点分治]树上的路径
- 【bzoj3784】【树上的路径】【点分治+堆+st表】
- [BZOJ3784]树上的路径 点分治序+ST表
- [BZOJ3784]树上的路径(点分治+dfs序+st表+堆)
- 树上的路径
- 3784: 树上的路径
- bzoj3784
- bzoj 3784: 树上的路径
- Codevs 2756 树上的路径
- 树上路径
- 树上路径
- 树上路径
- 【CODE[VS]】2756 树上的路径
- noip2013truck树上路径倍增
- 树上最长单色路径
- 树上最长单色路径
- iOS 国际化
- Druid数据库连接池简单使用介绍
- Android屏幕适配的两种方法
- PS5入门
- Open Source Threat Intelligence
- [bzoj3784]树上的路径
- QT GUI界面假死的处理
- LintCode- 单词切分
- 蓝桥杯_算法训练_K好数
- 189. Rotate Array
- 适配器模式
- UIUITableView头部图片拉伸放大效果
- id_rsa权限过高导致不能下载
- 2016蓝桥杯假期任务之《字串统计》