P4197 Peaks [Kruskal reconstruction Chairman tree tree +]

Reconstruction of part kruskal tree extract content in bzt fairy blog

Problem

In \ (Bytemountains \) have \ (n \) peaks, each has his peaks of height \ (H_i \) . There are some peaks are connected between the two-way road, a total of \ (M \) paths, each path having a hard value, the larger the value the more difficult to go, there are \ (Q \) group query, each query from the query point \ (V \) begins only after the value is less difficult \ (X \) peaks of the first path can reach \ (K \) high peaks, if no solution output \ (- 1 \) .

kruskal reconstructed tree is used to solve some, such as "inquiry began after right side from a certain point of not more than \ (val \) node can reach" problem
so it is clear that at the minimum spanning tree is optimal. . Other unwanted side may need to consider. .
That's when we ran kruskal re-built side. .
Kruskal reconstructed tree idea is to build the minimum spanning tree when not directly connected to the side but a new node and the value of the node is set to the right side and then make two connected blocks, respectively, as its representative point about son then allowed to become the new node communication throughout the block representative point
that, if \ (U \) \ (V \) do not communicate with
the \ (U \) \ (V \) points connected to the new node. . Incidentally, even the edges. . Then it becomes a tree. .

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) ;
  }

The following comes from a blog in bztminamoto

Suppose there are four nodes, asking them to reconstruct the Kruskal tree

We find the minimum spanning tree according to the method, first side-by-weight from small to large.

Then the first side is provided with a weight of 4, 1 and 2, two connecting blocks communication

Then create a new node 5, right to the point 4, 1 and 2 and the left and right as his son

The second edge weight value of 6, 3 and 4 are connected the two communication blocks

Then create a new node 6, 6 points to the right, and the 3 and 4 as his son about

Third side with a weight of 7, connections 1 and 2, we take the communication block is connected to the 4 and 6 (these two points is representative of the communication block)

Then create a new node 7, point 7 is set to the right, and the 5 and 6 as his son about

This is a reconstruction and Kruskal tree to built

Then ask this question is \ (k \) big
\ (k \) major problems are generally solved the Chairman of the tree. .
Therefore, the tree became the new Chairman of the trees into the dfs order to solve it (online). .

#include<bits/stdc++.h>
using namespace std ;
const int N = 2e5 + 5 ;
const int M = 5e5 + 5 ;
const int inf = INT_MAX ;
struct node { int v , nxt ; } e[N << 1] ;
struct Node { int u , v , w ; } q[M] , t[N << 1] ;
int n , m , Q ;
int rt[N] , h[N] ;
int ls[N << 5] , rs[N << 5] , sum[N << 5] ;
int val[N] ;
int head[N] , cnt = 0 ;
inline void add(int u , int v) { e[++ cnt] = { v , head[u]} ; head[u] = cnt ; }
inline bool cmp(Node x , Node y) { return x.w < y.w ; }
int fa[N] ; int tot ;
inline int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]) ; }
inline void kruskal() {
  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) ;
  }
}
int f[N][22], L[N] , R[N] ;
int b[N] , pop = 0 ;
inline void dfs(int u , int fa) {
  f[u][0] = fa ;
  for( int i = 1 ; i <= 19 ; i ++ ) f[u][i] = f[f[u][i - 1]][i - 1] ;
  L[u] = pop ;
  if(! head[u]) { b[++ pop] = u ; R[u] = pop ; return ; }
  for( int i = head[u] ; i ; i = e[i].nxt) {
    int v = e[i].v ; dfs(v , u) ;
  } R[u] = pop ;
}
inline void build(int l , int r , int & o) {
  o = ++ cnt ;
  if(l == r) return ;
  int mid = l + r >> 1 ;
  build(l , mid , ls[o]) ; build(mid + 1 , r , rs[o]) ;
}
inline void upd(int l , int r , int pre , int & o , int x) {
  o = ++ cnt ;
  ls[o] = ls[pre] ; rs[o] = rs[pre] ; sum[o] = sum[pre] ;
  if(l == r) { sum[o] ++ ; return ; }
  int mid = l + r >> 1 ;
  if(x <= mid) upd(l , mid , ls[pre] , ls[o] , x) ;
  else upd(mid + 1 , r , rs[pre] , rs[o] , x) ;
  sum[o] = sum[ls[o]] + sum[rs[o]] ;
}
inline int find_fa(int x , int k) {
  for(register int i = 19 ; ~ i ; i --)
    if(val[f[x][i]] <= k) x = f[x][i] ;
  return x ;
}
inline int query(int a , int b , int l , int r , int k) {
  if(l == r)
    if(k == sum[b] - sum[a]) return l ;
    else return 0 ;
  int x = sum[rs[b]] - sum[rs[a]] , mid = l + r >> 1 ;
  if(x >= k) return query(rs[a] , rs[b] , mid + 1 , r , k) ;
  else return query(ls[a] , ls[b] , l , mid , k - x) ;
}
signed main() {
  ios :: sync_with_stdio(false) ;
  cin.tie(nullptr) ;
  cout.tie(nullptr) ;
  cin >> n >> m >> Q ;
  val[0] = inf ;
  for( int i = 1 ; i <= n ; i ++ ) cin >> h[i] ;
  for( int i = 1 ; i <= n ; i ++ ) t[i].u = i , t[i].w = h[i] ;
  sort(t + 1 , t + n + 1 , cmp) ;
  for( int i = 1 ; i <= n ; i ++ ) h[t[i].u] = i ;
  for( int i = 1 ; i <= m ; i ++ ) { cin >> q[i].u >> q[i].v >> q[i].w ; }
  kruskal() ;
  dfs(tot , tot) ; cnt = 0 ;
  build(1 , n , rt[0]) ;
  for( int i = 1 ; i <= pop ; i ++)
    upd(1 , n , rt[i - 1] , rt[i] , h[b[i]]) ;
  t[0].w = -1 ;
  for( int i = 1 ; i <= Q ; i ++) {
    int v , x , k ; cin >> v >> x >> k ;
    int fa = find_fa(v , x) ;
    int ans = query(rt[L[fa]] , rt[R[fa]] , 1 , n , k) ;
    cout << t[ans].w << '\n' ;
  }
  return 0 ;
}

Guess you like

Origin www.cnblogs.com/Isaunoya/p/11780762.html