gym 101810 M. Greedy Pirate (LCA)

Topic: https://codeforc.es/gym/101810/problem/M

Meaning of the questions: give your tree, here are m queries, seeking u-> v is the maximum number, there are two points between the input side, the positive side there is the right, there are anti-anti-edge right, then Q u-> v can be subjected to the maximum weight is how much

Ideas: We begin to root for u we will find when we go where the non-v subtree we can all come back and finish the edges, where the sub-tree for v we can also reverse two sides are completed, uv's the shortest road can only go again, so this problem is transformed to find the longest chain issues, u-> v longest chain, but we have m queries, we can not always get through all the points come longest chain, we can in fact is the root, then the two arrays are recorded by positive and negative weights to the root of the distance from the current point, and then drawing it can be seen from their points of fact dis1 [u] -dis1 [lca (u, v)] + dis2  [v] -dis2 [lca (u, v)]

 

#include<bits/stdc++.h>
using namespace std;
#define mst(ss,b) memset((ss),(b),sizeof(ss))
const int N = 1e5+5;
int t,n,m,dis[N],dis1[N],fa[N][20],fa1[N][20],dep[N],dep1[N],vs[N],vs1[N];
struct nd{
    int to,w,w1;
};
vector<nd> g[N];
 
void init() {
    for(int i=1;i<=n;i++) g[i].clear();
    mst(dis,0),mst(fa,0),mst(dep,0), MST (VS, 0 ); 
    MST (DIS1, 0 ), MST (FA1, 0 ), MST (Dep 1, 0 ), MST (VS1, 0 ); 
} 
 
void DFS ( int X) { /// obtained each node of the root node to the distance, depth, father 
    VS [X] = . 1 ;
     for ( int I = 0 ; I <G [X] .size (); I ++ ) { 
        Nd TP = G [X] [I] ;
         int V = tp.to, tp.w = W, W1 = tp.w1;
         IF (VS [V]) Continue ; 
        FA [V] [ 0 ] = X; 
        FA1 [V] [0 ] = X; 
        DIS [V] = DIS [X] + W; 
        DIS1 [V] = DIS1 [X] + W1; 
        DEP [V] = DEP [X] + . 1 ; 
        Dep 1 [V] = Dep 1 [X] + . 1 ; 
        DFS (V); 
    } 
} 
 
void BZ () { /// multiplication preprocessing 
    for ( int J = . 1 ; J < 20 is ; J ++) /// FA [i] [J] denotes the node i 2 ^ j ancestor 
        for ( int I = . 1 ; I <= n-; I ++ ) 
            FA [I] [J] = FA [FA [I] [J- . 1 ]] [J- . 1], 
            FA1 [I] [J] = FA1 [FA1 [I] [J- . 1 ]] [J- . 1 ]; 
} 
 
int LCA ( int U, int V) {
     IF (DEP [U] <DEP [V] ) the swap (u, V); /// Note exchange u and v, not exchange DEP [u] and DEP [V] 
    int D = DEP [u] - DEP [V];
     for ( int I = 0 ; I < 20 is ; I ++) /// first adjusted to the same depth 
        IF (D & ( . 1 << I)) U = FA [U] [I];
     IF (U == V) return U;
     for ( int I = . 19 ; i> =0 ; i--) { /// Note that for backwards is, binary split, descending attempts 
        IF (FA [U] [I] =! FA [V] [I]) { 
            U = FA [U ] [I]; 
            V = FA [V] [I]; 
        } 
    } 
    return FA [U] [ 0 ]; 
} 
 
int main () {
     the while (~ Scanf ( " % D " , & T)) {
         the while (T - ) { 
            Scanf ( " % D " , & n-); 
            the init (); 
            Long  Long ANS = 0 ;
            for(int i=1;i<n;i++) {
                int a,b,c,d;
                scanf("%d%d%d%d",&a,&b,&c,&d);
                g[a].push_back({b,c,d});
                g[b].push_back({a,d,c});
                ans += c+d;
            }
            dep[1]=1,dis[1]=0;
            dep1[1]=1,dis1[1]=0;
            dfs(1);
            bz();
            scanf("%d",&m);
            for(int i=1;i<=m;i++) {
                int u,v;
                scanf("%d%d",&u,&v);
                printf("%lld\n",ans-(dis1[v]-dis1[lca(u,v)]+dis[u]-dis[lca(u,v)]));
            }
        }
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/Lis-/p/11387239.html
lca