Los looting Valley P3627 [plan]


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 }

 

Guess you like

Origin www.cnblogs.com/qqq1112/p/11255179.html