Tree links are divided into several chains in one sentence, and each chain is maintained using the data structure (tree array, SBT, Splay, line segment tree, and so on, if the complexity is O (logn), the first step of tree chain partitioning is to divide the tree's weight and edge. Define size (x) as the number of subtree nodes with x as the root, so that (u, v) is the biggest node in the son of u, then (u, v) is the duplicate edge, the remaining edges are light edges. Of course, it has two important properties: (1) In the light side (u, v), size (v) <= size (u/2) (2) from the root to a specific path, there are no more than N loose and no more than N loose paths. Of course, the splitting process can be divided into two dfs, or bfs. If it is two dfs, the first dfs is to find the duplicate edge, that is, to record all the duplicate edges. Then, the second dfs is to connect the duplicate edge to form a heavy chain. The specific process is to expand down along the duplicate edge at the root node and pull the heavy chain, which is not on the current heavy chain node, start from this node and pull a heavy chain. After division, each heavy chain is equivalent to a range, and then maintained using the data structure. All heavy chains are connected at the beginning and end, placed on the data structure, and then maintained as a whole. Here, of course, there are many arrays. Now I will introduce their respective functions: the siz [] array, used to save the top [] array of the number of subtree nodes with x as the root, used to save the son [] array of the top node of the chain of the current node, used to save the son-heavy dep [] array, used to save the depth of the current node fa [] array, used to save the father's tid [] array of the current node, used to save the new number rank [] array after each node is split in the tree, used to save the location in the online segment tree of the current node, now we can give the code for partitioning according to the description: First dfs: record all the duplicate Edges
void dfs1(int u,int father,int d) { dep[u]=d; fa[u]=father; siz[u]=1; for(int i=head[u];~i;i=next[i]) { int v=to[i]; if(v!=father) { dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } }
Second dfs: duplicate side into heavy chain
void dfs2(int u,int tp) { top[u]=tp; tid[u]=++tim; rank[tid[u]]=u; if(son[u]==-1) return; dfs2(son[u],tp); for(int i=head[u];~i;i=next[i]) { int v=to[i]; if(v!=son[u]&&v!=fa[u]) dfs2(v,v); } }
Of course, because the question sometimes requires a lot of sides, it is best not to use a two-dimensional array to represent the edge, apply the adjacent table or chain the forward star. Of course, an important operation is to modify the Edge Weight Value in the tree. How can I modify the Edge Weight of u to v? There are two cases: (1) if u and v are on the same heavy chain, then they are directly modified (2) if u and v are not on the same heavy chain, then, you can modify the u and v to the same heavy chain, this becomes the first case. Now the key question is how to place u and v on the same heavy chain? I will omit this question. Now, the basic analysis of the tree link splitting principle is complete!