Advertisement
Guest User

steak_b3_ans.c++

a guest
Jan 4th, 2017
2,846
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.86 KB | None | 0 0
  1. #include <cassert>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5.  
  6. #include <functional>
  7. #include <utility>
  8. #include <vector>
  9.  
  10. using namespace std;
  11.  
  12. template <typename Info>
  13. class DSU {
  14.   public:
  15.     DSU ( int n ) : jump (new int[n]), rank (new int [n]), info (new Info [n]) {
  16.       for (int i = 0; i < n; i++) {
  17.         jump[i] = i;
  18.         rank[i] = 0;
  19.       }
  20.     }
  21.     Info& operator [] ( int x ) {
  22.       return info[get (x)];
  23.     }
  24.     void merge ( int a, int b, const Info &comment ) {
  25.       a = get (a);
  26.       b = get (b);
  27.       if (rank[a] <= rank[b]) {
  28.         jump[a] = b;
  29.         rank[b] += rank[a] == rank[b];
  30.         info[b] = comment;
  31.       } else {
  32.         jump[b] = a;
  33.         info[a] = comment;
  34.       }
  35.     }
  36.   private:
  37.     int *jump, *rank;
  38.     Info *info;
  39.  
  40.     int get ( int x ) {
  41.       return jump[x] == x ? x : (jump[x] = get (jump[x]));
  42.     }
  43. };
  44.  
  45.  
  46. struct Treap {
  47.   int value, add;
  48.   int source, target, height;
  49.   int min_value, min_path;
  50.  
  51.   Treap *left, *right;
  52.  
  53.   Treap ( int _source, int _target, int _value ) : value (_value), add (0), source (_source), target (_target) {
  54.     height = rand ();
  55.     min_value = value, min_path = 0;
  56.     left = right = 0;
  57.   }
  58.  
  59.   Treap& operator += ( int sub ) {
  60.     add += sub;
  61.     return *this;
  62.   }
  63.  
  64.   void push () {
  65.     if (!add)
  66.       return;
  67.     if (left) {
  68.       left->add += add;
  69.     }
  70.     if (right) {
  71.       right->add += add;
  72.     }
  73.     value += add;
  74.     min_value += add;
  75.     add = 0;
  76.   }
  77.  
  78.   void recalc () {
  79.     min_value = value;
  80.     min_path = 0;
  81.     if (left && left->min_value + left->add < min_value) {
  82.       min_value = left->min_value + left->add;
  83.       min_path = -1;
  84.     }
  85.     if (right && right->min_value + right->add < min_value) {
  86.       min_value = right->min_value + right->add;
  87.       min_path = +1;
  88.     }
  89.   }
  90. };
  91.  
  92. Treap* treap_merge ( Treap *x, Treap *y ) {
  93.   if (!x)
  94.     return y;
  95.   if (!y)
  96.     return x;
  97.   if (x->height < y->height) {
  98.     x->push ();
  99.     x->right = treap_merge (x->right, y);
  100.     x->recalc ();
  101.     return x;
  102.   } else {
  103.     y->push ();
  104.     y->left = treap_merge (x, y->left);
  105.     y->recalc ();
  106.     return y;
  107.   }
  108. }
  109.  
  110. Treap* treap_getmin ( Treap *x, int &source, int &target, int &value ) {
  111.   assert (x);
  112.   x->push ();
  113.   if (x->min_path == 0) {
  114.     // memory leak, sorry
  115.     source = x->source;
  116.     target = x->target;
  117.     value = x->value + x->add;
  118.     return treap_merge (x->left, x->right);
  119.   } else if (x->min_path == -1) {
  120.     x->left = treap_getmin (x->left, source, target, value);
  121.     value += x->add;
  122.     x->recalc ();
  123.     return x;
  124.   } else if (x->min_path == +1) {
  125.     x->right = treap_getmin (x->right, source, target, value);
  126.     value += x->add;
  127.     x->recalc ();
  128.     return x;
  129.   } else
  130.     assert (0);
  131. }
  132.  
  133. Treap* treap_add ( Treap *x, int add ) {
  134.   if (!x)
  135.     return 0;
  136.   return &((*x) += add);
  137. }
  138.  
  139.  
  140. int main () {
  141.   int n, m;
  142.   while (scanf ("%d%d", &n, &m) == 2) {
  143.     Treap * g[n + 1];
  144.     for (int i = 0; i <= n; i++)
  145.       g[i] = 0;
  146.     for (int i = 1; i <= n; i++) {
  147.       int a;
  148.       assert (scanf ("%d", &a) == 1);
  149.       g[i] = treap_merge (g[i], new Treap (i, 0, a));
  150.     }
  151.     n++;
  152.     for (int i = 0; i < m; i++) {
  153.       int a, b, c;
  154.       assert (scanf ("%d%d%d", &a, &b, &c) == 3);
  155.       g[b] = treap_merge (g[b], new Treap (b, a, c));
  156.     }
  157.     DSU <pair <int, Treap*> > dsu (n + 1);
  158.     for (int i = 0; i < n; i++) {
  159.       dsu[i] = make_pair (i, g[i]);
  160.     }
  161.  
  162.     int ans = 0, k = n;
  163.     int jump[2 * n], jump_from[2 * n], parent[2 * n], c[n];
  164.     vector <int> children[2 * n];
  165.     memset (c, 0, sizeof (c[0]) * n);
  166.     memset (parent, -1, sizeof (parent[0]) * 2 * n);
  167.     vector <int> finish;
  168.     for (int i = 0; i < n; i++) {
  169.       if (dsu[i].first == 0)
  170.         continue;
  171.       int u = i;
  172.       c[u] = 1;
  173.       while (true) {
  174.         int source, target, value;
  175.         dsu[u].second = treap_getmin (dsu[u].second, source, target, value);
  176.         if (dsu[target] == dsu[u])
  177.           continue;
  178.         treap_add (dsu[u].second, -value);
  179.         ans += value;
  180.         jump_from[dsu[u].first] = source;
  181.         jump[dsu[u].first] = target;
  182.         if (dsu[target].first == 0)
  183.           break;
  184.         if (!c[target]) {
  185.           c[target] = 1;
  186.           u = target;
  187.           continue;
  188.         }
  189.         assert (k < 2 * n);
  190.         int node = k++, t = target;
  191.         parent[dsu[u].first] = node;
  192.         children[node].push_back (dsu[u].first);
  193.         dsu[u].first = node;
  194.         Treap *v = dsu[u].second;
  195.         while (dsu[t].first != node) {
  196.           int next = jump[dsu[t].first];
  197.           parent[dsu[t].first] = node;
  198.           children[node].push_back (dsu[t].first);
  199.           v = treap_merge (v, dsu[t].second);
  200.           dsu.merge (u, t, make_pair (node, v));
  201.           t = next;
  202.         }
  203.       }
  204.       u = i;
  205.       while (dsu[u].first) {
  206.         int next = jump[dsu[u].first];
  207.         finish.push_back (dsu[u].first);
  208.         dsu.merge (u, 0, make_pair (0, (Treap *)0));
  209.         u = next;
  210.       }
  211.     }
  212.     bool ok[k];
  213.     int res[n];
  214.     memset (ok, 0, sizeof (ok[0]) * k);
  215.     memset (res, -1, sizeof (res[0]) * n);
  216.     function <void (int, int)> add_edge = [&ok, &parent, &res, &n] ( int a, int b ) {
  217.       assert (0 <= a && a < n);
  218.       assert (0 <= b && b < n);
  219.       assert (res[a] == -1);
  220.       res[a] = b;
  221.       while (a != -1 && !ok[a]) {
  222.         ok[a] = true;
  223.         a = parent[a];
  224.       }
  225.     };
  226.     function <void (int)> reach = [&ok, &reach, &children, &jump, &jump_from, &add_edge]( int u ) {
  227.       if (!ok[u])
  228.         add_edge (jump_from[u], jump[u]);
  229.       for (auto x : children[u])
  230.         reach (x);
  231.     };
  232.     for (auto x : finish)
  233.        reach (x);
  234.     printf ("%d\n", ans);
  235.     for (int i = 1; i < n; i++)
  236.       printf ("%d%c", res[i] ? res[i] : -1, "\n "[i < n - 1]);
  237.   }
  238.   return 0;
  239. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement