Question: give you a forest with n nodes and m edges, and then specify q queries. Each time you query the nearest distance between the two vertices in the forest. N, m <= 10000, q <= 1 million
Solution: A very classic LCA is actually a very simple LCA question, but this question is given by a forest rather than a tree. The difference is that a for loop is used for multiple computations. I saw a blog about aiguoruan, which is easy to understand. Reference: tarjan's idea of using and querying the set in the solution: traverse the tree first, from the leaf node, the Child tree is merged into a tree. Then the child tree is merged into a tree. Search is performed during merging. exp: u is s, and t is the lca. First, enter s from the u node, and put s Under u. Then, t is not accessed, return to u and then enter t. Similarly, place t under u and find that s has been accessed. Then, the lca of s is also the lca of s and t, that is, f [s] in the consortium. Of course, f [s] Will Change: Assume that f [s] = u; f [u] = u; when u is connected to v, that is, f [u] = v; f [s] = v. This is the key method of tarjan for solving lca.
Test data:
5 3 2
1 3 2
2 4 3
5 2 3
1 4
4 5
C producer code:
[Cpp]
# Include <stdio. h>
# Include <string. h>
# Include <vector>
Using namespace std;
# Define MIN 11000
# Deprecision MAX 1100000
Struct node {
Int v, len;
} Cur;
Int dist [MIN], visit [MIN]; // dist [I] indicates the distance from I to the root node, and visit [I] determines whether it has traversed
Int n, m, q, ans [MAX], fa [MIN]; // ans [I] records what the I group query should output
Vector <node> tree [MIN], query [MIN]; // tree record forest, query record query
Void Initial (){
Memset (dist, 0, sizeof (dist ));
Memset (visit, 0, sizeof (visit ));
For (int I = 0; I <= n; ++ I)
Fa [I] = I, tree [I]. clear (), query [I]. clear ();
}
Void AddEdge (int a, int B, int c, int kind ){
If (kind = 0 ){
// Build
Cur. v = B, cur. len = c;
Tree [a]. push_back (cur );
}
Else {
// Offline query Sequence
Cur. v = B, cur. len = c;
Query [a]. push_back (cur );
}
}
Int Find (int n ){
// Query the set to find the parent node and compress the path
Int x = n, r;
While (fa [x]! = X) x = fa [x];
While (n! = X ){
R = fa [n];
Fa [n] = x, n = r;
}
Return x;
}
Void Tarjan (int now, int dis, int root ){
Fa [now] = now;
Dist [now] = dis;
Visit [now] = root;
Node fuck;
Int size = tree [now]. size ();
For (int I = 0; I <size; ++ I ){
Fuck = tree [now] [I];
If (! Visit [fuck. v]) {
Tarjan (fuck. v, dis + fuck. len, root );
Fa [fuck. v] = now;
}
}
Size = query [now]. size ();
For (int I = 0; I <size; ++ I ){
Fuck = query [now] [I];
If (visit [fuck. v]) {// a-> B, if B is not traversed, then B-> a can be calculated
If (visit [fuck. v]! = Root) ans [fuck. len] =-1; // in different branches
Else ans [fuck. len] = dist [now] + dist [fuck. v]-2 * dist [Find (fuck. v)];
}
}
}
Int main ()
{
Int I, j, k;
Int ta, tb, a, B, c;
While (scanf ("% d", & n, & m, & q )! = EOF ){
Initial ();
For (I = 1; I <= m; ++ I ){
Scanf ("% d", & a, & B, & c );
AddEdge (a, B, c, 0 );
AddEdge (B, a, c, 0 );
}
For (I = 1; I <= q; ++ I ){
Scanf ("% d", & a, & B );
AddEdge (a, B, I, 1); // used for vector offline Query
AddEdge (B, a, I, 1 );
}
// Solve the problem with Tarjan
For (I = 1; I <= n; ++ I)
If (! Visit [I]) Tarjan (I, 0, I); // traverse the entire tree with the root of I
For (I = 1; I <= q; ++ I) www.2cto.com
If (ans [I]! =-1) printf ("% d \ n", ans [I]);
Else printf ("Not connected \ n ");
}
}
Author: woshi250hua