HDU 4297 one and one story (maintaining the LCA in the forest)

Source: Internet
Author: User

There are n rooms, and each room has only one outbound direction pointing to the other room. Now two people are given in two rooms. Ask them the minimum number of paths to join.

Solution: Observe the form of a graph. Because N points have n edges and each vertex outdegree is 1, it can be considered as a forest, each tree in the forest adds an edge to form a ring, and the ring is the root node (it can be considered that there is no outbound edge after the contraction, that is, there is no parent node ).

Obviously, the two points cannot be reached when they belong to different trees. Because of the particularity of the graph, we do not use strong connectivity, but use and query the set ring, it is also convenient to mark the relative position of each vertex on the ring.

If two points are on the same tree, if they are not on the same branch of the root node, they must first go to the ring, then one person does not move the other one (as for whether to let a go or B, the superior and inferior arcs should be judged based on the relative positions of the two points on the ring). If the two points are in the same branch, that is the path between two points on the tree.

If there is no such ring, it is a normal LCA problem in the forest, but due to point reduction, it is necessary to add a virtual root node 0, the point on all rings can be the root node of the forest neutron tree. The virtual root node connects the edge to the root node of all trees, and then performs the LCA. If we find that the LCA between the two AB points is 0, then judge whether two points are in a subtree. If they are not in or out of reach, then judge the arc and inferior arc. If they are not 0, it is equivalent to the LCA of a tree, you can directly determine the shortest distance between two points.

In addition, the requirements for the output of the answer are a little painful. During the game, I saw a wrong wa for several times ,,,

# Pragma comment (linker, "/Stack: 16777216") # include <cstdio> # include <cstdlib> # include <iostream> # include <string. h ># include <queue> using namespace STD; const int maxn = 1000010; struct node {int be, NE, weight; void Init (int B, int e, int V) {Be = B; Ne = E; Weight = V ;}}; int rmq [maxn * 2]; // must 1 -- N !!! Struct rmq {// sparse treeint lg [maxn + 1], Minn [20] [maxn + 1], n; rmq () {lg [0] =-1; for (INT I = 1; I <= maxn; I ++) {lg [I] = (I & (I-1) = 0 )? Lg [I-1] + 1: lg [I-1]; Minn [0] [I] = I;} void Init (INT N) {This-> N = N; For (INT I = 1; I <= lg [N]; I ++) for (Int J = 1; j <= n + 1-(1 <I); j ++) {int A = Minn [I-1] [J]; int B = Minn [I-1] [J + (1 <(I-1)]; minn [I] [J] = rmq [a] <rmq [B]? A: B ;}} int getmin (INT S, int t) {If (S> T) {int temp = T; t = s; S = temp ;} int K = lg [T-S + 1]; int A = Minn [k] [s]; int B = Minn [k] [T-(1 <K) + 1]; If (rmq [a] <rmq [B]) return a; elsereturn B ;}} st; int root [maxn]; struct LCA {int N, Len, E [maxn]; node Buf [maxn * 2]; int f [maxn * 2], POS [maxn], CNT; // Euler's sequence (the element retrieved from the I-th traversal): CNT; int dis [maxn]; // void Init (INT N) Distance from each point to the root node) {This-> N = N; Len = 0; memset (E, -1, sizeof (e);} void addedge (int A, int B, int W) {Buf [Len]. init (B, E [a], W); e [a] = Len ++; Buf [Len]. init (A, E [B], W); e [B] = Len ++;} int query (int A, int B) {int K = ST. getmin (Pos [a], POS [B]); Return f [k];} void DFS (int A, int column) {f [++ CNT] =; rmq [CNT] = lev; POS [a] = CNT; For (INT I = E [a]; I! =-1; I = Buf [I]. Ne) {int B = Buf [I]. Be; If (Pos [B]! =-1) continue; DIS [B] = dis [a] + Buf [I]. weight; DFS (B, Ev + 1); F [++ CNT] = A; rmq [CNT] = lev;}} void dfs2 (int A, int R) {root [a] = r; For (INT I = E [a]; I! =-1; I = Buf [I]. ne) if (root [Buf [I]. be] =-1) dfs2 (BUF [I]. be, R);} void solve (INT root) {CNT = 0; memset (Pos,-1, sizeof (POS); memset (DIS, 0, sizeof (DIS); DFS (root, 0); ST. init (2 * N-1) ;}} LCA; int NXT [maxn], n; int CC [maxn], POS [maxn], Len [maxn], num; int f [maxn]; int find (int x) {If (X! = F [x]) f [x] = find (F [x]); Return f [X];} void circle () {for (INT I = 1; I <= N; I ++) f [I] = I; num = 0; memset (CC,-1, sizeof (CC); memset (Pos,-1, sizeof (POS); For (INT I = 1; I <= N; I ++) {int A = find (I ); int B = find (NXT [I]); if (a = B) CC [I] = ++ num; F [a] = B ;} for (INT I = 1; I <= N; I ++) if (CC [I]! =-1) {int K = NXT [I]; int CNT = 0; POS [I] = ++ CNT; root [I] = I; while (K! = I) {pos [k] = ++ CNT; root [k] = K; CC [k] = Cc [I]; k = NXT [k];} len [CC [I] = CNT ;}int main () {int m; while (scanf ("% d", & N, & M )! = EOF) {LCA. init (n + 1); memset (root,-1, sizeof (Root); For (INT I = 1; I <= N; I ++) scanf ("% d", NXT + I); Circle (); For (INT I = 1; I <= N; I ++) if (root [I]! = I) LCA. addedge (NXT [I], I, 1); For (INT I = 1; I <= N; I ++) {If (root [I] = I) {LCA. dfs2 (I, I); LCA. addedge (0, I, 0) ;}} LCA. solve (0); int A, B; while (M --> 0) {scanf ("% d", & A, & B); int P = LCA. query (a, B); If (P! = 0) printf ("% d \ n", (LCA. dis [a]-LCA. dis [p]), (LCA. dis [B]-LCA. dis [p]); else {int Ra = root [a], rB = root [B]; If (CC [Ra]! = Cc [RB]) printf ("-1-1 \ n"); else {int CNT = Len [CC [Ra]; int temp1 = LCA. dis [a]; int temp2 = LCA. dis [B]; // A --> BIF (Pos [Ra] <POS [RB]) temp1 + = POS [RB]-pos [Ra]; elsetemp1 + = (CNT-pos [Ra] + POS [RB]); // B --> aint temp3 = LCA. dis [a]; int temp4 = LCA. dis [B]; If (Pos [RB] <POS [Ra]) temp4 + = POS [Ra]-pos [RB]; elsetemp4 + = (CNT-pos [RB] + POS [Ra]); If (max (temp1, temp2) <max (temp3, temp4 )) printf ("% d \ n", temp1, temp2); If (max (temp1, temp2)> MAX (temp3, temp4 )) printf ("% d \ n", temp3, temp4); If (max (temp1, temp2) = max (temp3, temp4) {If (min (temp1, temp2) <min (temp3, temp4) printf ("% d \ n", temp1, temp2); If (min (temp1, temp2)> min (temp3, temp4) printf ("% d \ n", temp3, temp4); If (min (temp1, temp2) = min (temp3, temp4 )) {If (temp1> = temp2) printf ("% d \ n", temp1, temp2); elseprintf ("% d \ n", temp3, temp4) ;}}}}} return 0 ;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.