P4197 Peaks [克鲁斯卡尔重构树 + 主席树]

风格不统一 提交于 2019-12-03 06:34:01

部分kruskal重构树内容摘抄于bzt神仙的blog

Problem

\(Bytemountains\)\(n\)座山峰,每座山峰有他的高度\(h_i\) 。有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走,现在有\(Q\)组询问,每组询问询问从点\(v\)开始只经过困难值小于等于\(x\)的路径所能到达的山峰中第\(k\)高的山峰,如果无解输出\(-1\)

kruskal重构树是用来解决一些诸如“查询从某个点开始 经过边权不超过\(val\)所能到达的节点”的问题
所以很显然 在最小生成树上是最优的。。其他多余的边可以不需要考虑。。
那我们在跑kruskal的时候重新建边。。
克鲁斯卡尔重构树的思想就是在建最小生成树的时候不是直接连边 而是新建一个节点 并把这个节点的值设为边权 然后令两个连通块的代表点分别作为它的左右儿子 然后令这个新节点成为整个连通块的代表点
即如果\(u\) \(v\)不连通

sort(q + 1 , q + m + 1 , cmp) ;
  for( int i = 1 ; i <= n ; i ++ ) fa[i] = i ;
  tot = n ;
  for( int i = 1 ; i <= m ; i ++ ) {
    int u = find(q[i].u) , v = find(q[i].v) ;
    if(u == v) continue ;
    val[++ tot] = q[i].w ; fa[tot] = fa[u] = fa[v] = tot ;
    add(tot , u) ; add(tot , v) ;
  }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!