- Exam: Luo Gu
- Question: 3627
- Title: looting plan
- link:https://www.luogu.org/problem/P3627
Thinking: This question is a Tarjan + longest road title. First, we put each strongly connected component Tarjan shrunk to a point, and that point right record strongly connected component and (because when someone will walk into that after a strongly connected component of all money will be strongly connected component he took go (perimeter would be finished?)), then we have the right to point to the edge of the right, then to the starting point where the strongly connected components of the longest running road, finally will be able to calculate the starting point from where the strongly connected components of an end to any strongly connected components where the maximum distance (maximum value of money), the output is a maximum strongly connected components is taken from a end point is located where the strongly connected components to an arbitrary starting point.
Details:
- About how the right point into the right side: very simple, set u -> k there is a way, q [i] is the weight of point i, the right side is the value of q [u], and finally we just put q [ the last point weights (end)] plus enough.
- How to build on edge: Edge simply not in the same strongly connected components can be connected together like a connect (Note: It is strongly connected components even where the two points).
- On how to run the longest road: We only had the shortest, but never learned how to run the longest road, so we have of the unknown becomes known, the longest path into the shortest. You think about it, if we build the right side is negative, it is not possible to run the most short-circuited? And finally the distance * -1 would be finished?
code:
. 1 #include <bits / STDC ++ H.> 2 #define INF 0x3f3f3f3f . 3 the using namespace STD; . 4 Stack < int > PRU; . 5 int n-, m, P, head [ 500001 ], Q [ 500001 ], COL [ 500001 ], Color, DFN [ 500001 ], Low [ 500001 ], S, E [ 500001 ], SUM [ 500001 ], Z, NUM, VIS [ 500001 ], DIS [ 500001 ], ANS; // variables too much bother to explain, sense about it. . . . 6 struct Node // deposit side 7 { . 8 int Next, to, Val; . 9 } STU [ 500001 ]; 10 Queue <Node> G; // for temporarily storing edge . 11 inline void the Add ( int X, int Y, int Z) 12 is { 13 is STU [+ NUM +] = .next head [X]; 14 STU [NUM] .to = Y; 15 STU [NUM] .val = Z; 16 head [X] = NUM; . 17 return ; 18 is } . 19 inline void Tarjan (int u)//Tarjan算法,这里用于缩点 20 { 21 dfn[u] = low[u] = ++z; 22 vis[u] = 1; 23 pru.push(u); 24 for(register int i = head[u]; i; i = stu[i].next) 25 { 26 int k = stu[i].to; 27 if(!vis[k]) 28 { 29 tarjan(k); 30 low[u] = min(low[u], low[k]); 31 } 32 else if(!col[k]) 33 { 34 low[u] = min(low[u], dfn[k]); 35 } 36 } 37 if(dfn[u] == low[u]) 38 { 39 col[u] = ++color; 40 sum[color] += q[u];//权值和 41 while(pru.top() != u) 42 { 43 col[pru.top()] = color; 44 sum[color] += q[pru.top()];//权值和 45 pru.pop (); 46 is } 47 pru.pop (); 48 } 49 return ; 50 } 51 is inline void SPFA ( int S) // find the shortest template the SPFA 52 is { 53 is Queue < int > PRU; 54 is Memset (VIS , 0 , the sizeof (VIS)); 55 Memset (DIS, INF, the sizeof (DIS)); 56 is pru.push (S); 57 is DIS [S] = 0 ; 58 vis[s] = 1; 59 while(!pru.empty()) 60 { 61 int u = pru.front(); 62 pru.pop(); 63 vis[u] = 0; 64 for(register int i = head[u]; i; i = stu[i].next) 65 { 66 int k = stu[i].to; 67 if(dis[k] > dis[u] + stu[i].val) 68 { 69 dis[k] = dis[u] + stu[i].val; 70 if(!vis[k]) 71 { 72 vis[k] = 1; 73 pru.push(k); 74 } 75 } 76 } 77 } 78 return; 79 } 80 inline void init()//初始化 81 { 82 memset(head, 0, sizeof(head)); 83 for(register int i = 1; i <= 100000; ++i) 84 { 85 stu[i].next = 0; 86 stu[i].to = 0; 87 stu[i].val = 0; 88 } 89 num = 0; 90 return; 91 } 92 inline void add_edge() 93 { 94 for(register int u = 1; u <= n; ++u) 95 { 96 for(Register int I = head [U]; I; I = STU [I] .next) 97 { 98 int K = STU [I] .to; 99 IF (! COL [K] = COL [U]) // not only in a strongly connected component built edge 100 { 101 // need to temporarily put to G, because if it is not a lot of things that the initialization built another side, will ....... 102 G.push (COL Node {[U], COL [K], -sum [COL [U]]}); // be built negative-side right (the longest path which can be converted to the shortest) 103 } 104 } 105 } 106 the init (); // initialize 107 the while (G.empty ()!) //After initialization Reload edge 108 { 109 Node P = G.front (); 110 the Add (p.next, p.to, p.val); // build edge 111 G.pop (); 112 } 113 return ; 114 } 115 Signed main () 1 16 { 117 Scanf ( " % D% D " , & n-, & m); 1 18 for (Register int I = . 1 , X, Y; I <= m; ++ I) 119 { 120 Scanf ( " % D% D ", &x, &y); 121 add(x, y, 0); 122 } 123 for(register int i = 1; i <= n; ++i) 124 { 125 scanf("%d", &q[i]); 126 } 127 scanf("%d %d", &s, &p); 128 for(register int i = 1; i <= p; ++i) 129 { 130 scanf("D% " , & E [I]); 131 is } 132 for (Register int I = . 1 ; I <= n-; ++ I) 133 { 134 IF (! VIS [I]) 135 { 136 Tarjan (I); 137 } 138 } 139 add_edge member (); // build edge 140 SPFA (COL [S]); // start from the starting point where the strongly connected components in the 141 is for (Register int I = . 1 ; I <= P; ++ I ) 142 { 143 ANS = max (ANS, DIS [COL [E [I]]] * - . 1 / * Do not forget to put it back into positive numbers * / + [COL [E [I]]] SUM / * Do not add the end where strong Unicom weight component * / ); 144 } 145 the printf ( " % D " , ANS); 146 return 0 ; 147 }