Train Tracks

That’s right. I’m a Purdue student, and I shamelessly wrote a problem about trains.

There are $n$ stations and $m$ trains. The stations are connected by $n-1$ one-directional railroads that form a tree rooted at station $1$. All railroads are pointed in the direction from the root station $1$ to the leaves. A railroad connects a station $u$ to a station $v$, and has a distance $d$, meaning it takes $d$ time to travel from $u$ to $v$. Each station with at least one outgoing railroad has a switch that determines the child station an incoming train will be directed toward. For example, it might look like this:

Here, stations $1$ and $3$ have switches directed toward stations $2$ and $4$, respectively.

Initially, no trains are at any station. Train $i$ will enter station $1$ at time $t_i$. Every unit of time, starting at time $1$, the following two steps happen:

  1. You can switch at most one station to point to a different child station. A switch change takes effect before step $2$.
  2. For every train that is on a station $u$, it is directed toward the station $v$ indicated by $u$’s switch. So, if the railroad from $u$ to $v$ has distance $d$, the train will enter station $v$ in $d$ units of time from now.

Every train has a destination station $s_i$. When it enters $s_i$, it will stop there permanently. If at some point the train is going in the wrong direction, so that it will never be able to reach $s_i$ no matter where the switches point, it will immediately explode.

Find the latest possible time of the first explosion if you change switches optimally, or determine that you can direct every train to its destination so that no explosion occurs. Also, find the minimum number of times you need to change a switch to achieve this.Input

The first line contains two integers $n$ and $m$ ($1\le n,m\le 10^5$) — the number of stations and trains, respectively.

The next $n-1$ lines describe the railroads. The $i$-th line contains three integers $u,v,d$ ($1\le u,v\le n$, $1\le d\le 10^9$), denoting a railroad from station $u$ to station $v$ with distance $d$. It is guaranteed that the railroads form a tree rooted at station $1$. The switch of a station $u$ is initially directed towards the last outgoing railroad from $u$ that appears in the input.

The next $m$ lines describe the trains. The $i$-th line contains two integers $s_i,t_i$ ($1\le s_i\le n$, $1\le t_1<t_2<\cdots<t_m\le 10^9$) — the destination station and the time the $i$-th train enters station $1$, respectively.Output

Output two integers: the latest possible time of the first explosion (or $-1$ if it is possible to never have an explosion) and the minimum number of switch changes to achieve it.Examplesinput

5 4
1 2 1
1 3 2
3 4 1
3 5 3
2 1
4 2
2 6
5 10

output

-1 6

input

5 4
1 2 1
1 3 2
3 4 1
3 5 3
5 1
4 2
4 3
2 4

output

4 0

input

11 6
1 2 1
1 3 2
3 4 1
3 5 2
5 6 1
5 7 2
7 8 1
7 9 2
9 10 1
9 11 1
2 1
8 3
6 5
10 7
4 9
2 11

output

11 4

Note

For the first test, here’s an example timeline:

  • At time $1$, train $1$ enters station $1$. We switch station $1$ to point to station $2$. Train $1$ is directed to station $2$.
  • At time $2$, train $2$ enters station $1$, and train $1$ enters station $2$, where it stops permanently. We switch station $1$ to point to station $3$. Train $2$ is directed to station $3$.
  • At time $4$, train $2$ enters station $3$. We switch station $3$ to point to station $4$. Train $2$ is directed to station $4$.
  • At time $5$, train $2$ enters station $4$, where it stops permanently.
  • At time $6$, train $3$ enters station $1$. We switch station $1$ to point to station $2$. Train $3$ is directed to station $2$.
  • At time $7$, train $3$ enters station $2$, where it stops permanently. We switch station $3$ to point to station $5$.
  • At time $10$, train $4$ enters station $1$. We switch station $1$ to point to station $3$. Train $4$ is directed to station $3$.
  • At time $12$, train $4$ enters station $3$. Train $4$ is directed to station $5$.
  • At time $15$, train $4$ enters station $5$, where it stops permanently.

For the second test, we switch nothing. At time $4$, train $2$ is directed to station $5$ and train $4$ is directed to station $3$. They both explode. It is impossible to prevent an explosion by time $4$.

For the third test, denote a switch change by $(u\to v,t)$ if we make station $u$ point to station $v$ at time $t$. One solution is to make these $4$ switch changes: $(1\to 2,1)$,$(1\to 3,2)$,$(7\to 8,5)$,$(5\to 6,8)$. At time $11$, trains $4$,$5$, and $6$ explode. It is impossible to prevent an explosion by time $11$.

Solution:

#include &lt;bits/stdc++.h&gt;

using namespace std;

template &lt;typename A, typename B&gt;
string to_string(pair&lt;A, B&gt; p);

template &lt;typename A, typename B, typename C&gt;
string to_string(tuple&lt;A, B, C&gt; p);

template &lt;typename A, typename B, typename C, typename D&gt;
string to_string(tuple&lt;A, B, C, D&gt; p);

string to_string(const string&amp; s) {
return '"' + s + '"';
}

string to_string(const char* s) {
return to_string((string) s);
}

string to_string(bool b) {
return (b ? "true" : "false");
}

string to_string(vector&lt;bool&gt; v) {
bool first = true;
string res = "{";
for (int i = 0; i &lt; static_cast&lt;int&gt;(v.size()); i++) {
if (!first) {
res += ", ";
}
first = false;
res += to_string(v[i]);
}
res += "}";
return res;
}

template &lt;size_t N&gt;
string to_string(bitset&lt;N&gt; v) {
string res = "";
for (size_t i = 0; i &lt; N; i++) {
    res += static_cast&lt;char&gt;('0' + v[i]);
}
return res;
}

template &lt;typename A&gt;
string to_string(A v) {
bool first = true;
string res = "{";
for (const auto &amp;x : v) {
if (!first) {
res += ", ";
}
first = false;
res += to_string(x);
}
res += "}";
return res;
}

template &lt;typename A, typename B&gt;
string to_string(pair&lt;A, B&gt; p) {
return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template &lt;typename A, typename B, typename C&gt;
string to_string(tuple&lt;A, B, C&gt; p) {
return "(" + to_string(get&lt;0&gt;(p)) + ", " + to_string(get&lt;1&gt;(p)) + ", " + to_string(get&lt;2&gt;(p)) + ")";
}

template &lt;typename A, typename B, typename C, typename D&gt;
string to_string(tuple&lt;A, B, C, D&gt; p) {
return "(" + to_string(get&lt;0&gt;(p)) + ", " + to_string(get&lt;1&gt;(p)) + ", " + to_string(get&lt;2&gt;(p)) + ", " + to_string(get&lt;3&gt;(p)) + ")";
}

void debug_out() { cerr &lt;&lt; endl; }

template &lt;typename Head, typename... Tail&gt;
void debug_out(Head H, Tail... T) {
cerr &lt;&lt; " " &lt;&lt; to_string(H);
  debug_out(T...);
}

#ifdef LOCAL
#define debug(...) cerr &lt;&lt; "[" &lt;&lt; #__VA_ARGS__ &lt;&lt; "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

class node {
 public:
  int id;
  node* l;
  node* r;
  node* p;
  bool rev;
  int sz;
  long long val;
  bool put;

  node(int _id) {
    id = _id;
    l = r = p = nullptr;
    rev = false;
    sz = 1;
    val = 0;
    put = false;
  }

  void unsafe_reverse() {
    rev ^= 1;
    swap(l, r);
    pull();
  }

  void unsafe_Apply(long long what) {
    val = what;
    put = true;
  }

  void push() {
    if (rev) {
      if (l != nullptr) {
        l-&gt;unsafe_reverse();
}
if (r != nullptr) {
r-&gt;unsafe_reverse();
}
rev = 0;
}
if (put) {
if (l != nullptr) {
l-&gt;unsafe_Apply(val);
}
if (r != nullptr) {
r-&gt;unsafe_Apply(val);
}
put = false;
}
}

void pull() {
sz = 1;
if (l != nullptr) {
l-&gt;p = this;
sz += l-&gt;sz;
}
if (r != nullptr) {
r-&gt;p = this;
sz += r-&gt;sz;
}
}
};

void debug_node(node* v, string pref = "") {
#ifdef LOCAL
if (v != nullptr) {
debug_node(v-&gt;r, pref + " ");
cerr &lt;&lt; pref &lt;&lt; "-" &lt;&lt; " " &lt;&lt; v-&gt;id &lt;&lt; '\n';
      debug_node(v-&gt;l, pref + " ");
} else {
cerr &lt;&lt; pref &lt;&lt; "-" &lt;&lt; " " &lt;&lt; "nullptr" &lt;&lt; '\n';
    }
  #endif
}

namespace splay_tree {

bool is_bst_root(node* v) {
  if (v == nullptr) {
    return false;
  }
  return (v-&gt;p == nullptr || (v-&gt;p-&gt;l != v &amp;&amp; v-&gt;p-&gt;r != v));
}

void rotate(node* v) {
node* u = v-&gt;p;
assert(u != nullptr);
u-&gt;push();
v-&gt;push();
v-&gt;p = u-&gt;p;
if (v-&gt;p != nullptr) {
if (v-&gt;p-&gt;l == u) {
v-&gt;p-&gt;l = v;
}
if (v-&gt;p-&gt;r == u) {
v-&gt;p-&gt;r = v;
}
}
if (v == u-&gt;l) {
u-&gt;l = v-&gt;r;
v-&gt;r = u;
} else {
u-&gt;r = v-&gt;l;
v-&gt;l = u;
}
u-&gt;pull();
v-&gt;pull();
}

void splay(node* v) {
if (v == nullptr) {
return;
}
while (!is_bst_root(v)) {
node* u = v-&gt;p;
if (!is_bst_root(u)) {
if ((u-&gt;l == v) ^ (u-&gt;p-&gt;l == u)) {
rotate(v);
} else {
rotate(u);
}
}
rotate(v);
}
}

pair&lt;node*, int&gt; find(node* v, const function&lt;int(node*)&gt; &amp;go_to) {
if (v == nullptr) {
return {nullptr, 0};
}
splay(v);
int dir;
while (true) {
v-&gt;push();
dir = go_to(v);
if (dir == 0) {
break;
}
node* u = (dir == -1 ? v-&gt;l : v-&gt;r);
if (u == nullptr) {
break;
}
v = u;
}
splay(v);
return {v, dir};
}

node* get_leftmost(node* v) {
return find(v, [&amp;](node*) { return -1; }).first;
}

node* get_rightmost(node* v) {
return find(v, [&amp;](node*) { return 1; }).first;
}

node* get_kth(node* v, int k) { // 0-indexed
pair&lt;node*, int&gt; p = find(v, [&amp;](node* u) {
if (u-&gt;l != nullptr) {
if (u-&gt;l-&gt;sz &gt; k) {
return -1;
}
k -= u-&gt;l-&gt;sz;
}
if (k == 0) {
return 0;
}
k--;
return 1;
});
return (p.second == 0 ? p.first : nullptr);
}

int get_position(node* v) { // 0-indexed
splay(v);
return (v-&gt;l != nullptr ? v-&gt;l-&gt;sz : 0);
}

node* get_bst_root(node* v) {
splay(v);
return v;
}

pair&lt;node*, node*&gt; split(node* v, const function&lt;bool(node*)&gt; &amp;is_right) {
if (v == nullptr) {
return {nullptr, nullptr};
}
pair&lt;node*, int&gt; p = find(v, [&amp;](node* u) { return is_right(u) ? -1 : 1; });
v = p.first;
v-&gt;push();
if (p.second == -1) {
node* u = v-&gt;l;
if (u == nullptr) {
return {nullptr, v};
}
v-&gt;l = nullptr;
u-&gt;p = v-&gt;p;
u = get_rightmost(u);
v-&gt;p = u;
v-&gt;pull();
return {u, v};
} else {
node* u = v-&gt;r;
if (u == nullptr) {
return {v, nullptr};
}
v-&gt;r = nullptr;
v-&gt;pull();
return {v, u};
}
}

pair&lt;node*, node*&gt; split_leftmost_k(node* v, int k) {
return split(v, [&amp;](node* u) {
int left_and_me = (u-&gt;l != nullptr ? u-&gt;l-&gt;sz : 0) + 1;
if (k &gt;= left_and_me) {
k -= left_and_me;
return false;
}
return true;
});
}

node* merge(node* v, node* u) {
if (v == nullptr) {
return u;
}
if (u == nullptr) {
return v;
}
v = get_rightmost(v);
assert(v-&gt;r == nullptr);
splay(u);
v-&gt;push();
v-&gt;r = u;
v-&gt;pull();
return v;
}

int count_left(node* v, const function&lt;bool(node*)&gt; &amp;is_right) {
if (v == nullptr) {
return 0;
}
pair&lt;node*, int&gt; p = find(v, [&amp;](node* u) { return is_right(u) ? -1 : 1; });
node* u = p.first;
return (u-&gt;l != nullptr ? u-&gt;l-&gt;sz : 0) + (p.second == 1);
}

node* add(node* r, node* v, const function&lt;bool(node*)&gt; &amp;go_left) {
pair&lt;node*, node*&gt; p = split(r, go_left);
return merge(p.first, merge(v, p.second));
}

node* remove(node* v) { // returns the new root
splay(v);
v-&gt;push();
node* x = v-&gt;l;
node* y = v-&gt;r;
v-&gt;l = v-&gt;r = nullptr;
node* z = merge(x, y);
if (z != nullptr) {
z-&gt;p = v-&gt;p;
}
v-&gt;p = nullptr;
v-&gt;push();
v-&gt;pull(); // now v might be reusable...
return z;
}

node* next(node* v) {
splay(v);
v-&gt;push();
if (v-&gt;r == nullptr) {
return nullptr;
}
v = v-&gt;r;
while (v-&gt;l != nullptr) {
v-&gt;push();
v = v-&gt;l;
}
splay(v);
return v;
}

node* prev(node* v) {
splay(v);
v-&gt;push();
if (v-&gt;l == nullptr) {
return nullptr;
}
v = v-&gt;l;
while (v-&gt;r != nullptr) {
v-&gt;push();
v = v-&gt;r;
}
splay(v);
return v;
}

int get_size(node* v) {
splay(v);
return (v != nullptr ? v-&gt;sz : 0);
}

template&lt;typename... T&gt;
void Apply(node* v, T... args) {
splay(v);
v-&gt;unsafe_Apply(args...);
}

void reverse(node* v) {
splay(v);
v-&gt;unsafe_reverse();
}

}  // namespace splay_tree

using namespace splay_tree;

template &lt;bool rooted&gt;
class link_cut_tree {
public:
int n;
vector&lt;node*&gt; nodes;

link_cut_tree(int _n) : n(_n) {
nodes.resize(n);
for (int i = 0; i &lt; n; i++) {
      nodes[i] = new node(i);
    }
  }

  int add_node() {
    int id = (int) nodes.size();
    nodes.push_back(new node(id));
    return id;
  }

  vector&lt;int&gt; check;

void expose(node* v, bool do_cut = false) {
node* r = nullptr;
node* u = v;
check.clear();
while (u != nullptr) {
splay(u);
if (r != nullptr || do_cut) {
u-&gt;push();
u-&gt;r = r;
u-&gt;pull();
}
if (u-&gt;p != nullptr) {
check.push_back(u-&gt;p-&gt;id);
}
r = u;
u = u-&gt;p;
}
splay(v);
assert(v-&gt;p == nullptr);
}

int get_root(int i) {
node* v = nodes[i];
expose(v);
return get_leftmost(v)-&gt;id;
}

bool link(int i, int j) { // for rooted: (x, parent[x])
if (i == j) {
return false;
}
node* v = nodes[i];
node* u = nodes[j];
if (rooted) {
splay(v);
if (v-&gt;p != nullptr || v-&gt;l != nullptr) {
return false; // not a root
}
} else {
make_root(i);
}
expose(u);
if (v-&gt;p != nullptr) {
return false;
}
v-&gt;p = u;
return true;
}

bool cut(int i, int j) { // for rooted: (x, parent[x])
if (i == j) {
return false;
}
node* v = nodes[i];
node* u = nodes[j];
expose(u);
splay(v);
if (v-&gt;p != u) {
if (rooted) {
return false;
}
swap(u, v);
expose(u);
splay(v);
if (v-&gt;p != u) {
return false;
}
}
v-&gt;p = nullptr;
return true;
}

bool cut(int i) { // only for rooted
assert(rooted);
node* v = nodes[i];
expose(v);
v-&gt;push();
if (v-&gt;l == nullptr) {
return false; // already a root
}
v-&gt;l-&gt;p = nullptr;
v-&gt;l = nullptr;
v-&gt;pull();
return true;
}

bool connected(int i, int j) {
if (i == j) {
return true;
}
node* v = nodes[i];
node* u = nodes[j];
expose(v);
expose(u);
return v-&gt;p != nullptr;
}

int lca(int i, int j) {
if (i == j) {
return i;
}
node* v = nodes[i];
node* u = nodes[j];
expose(v);
expose(u);
if (v-&gt;p == nullptr) {
return -1;
}
splay(v);
if (v-&gt;p == nullptr) {
return v-&gt;id;
}
return v-&gt;p-&gt;id;
}

bool is_ancestor(int i, int j) {
if (i == j) {
return true;
}
node* v = nodes[i];
node* u = nodes[j];
expose(u);
splay(v);
return v-&gt;p == nullptr &amp;&amp; u-&gt;p != nullptr;
}

void make_root(int i) {
assert(!rooted);
node* v = nodes[i];
expose(v);
reverse(v);
}

node* get_path_from_root(int i) {
node* v = nodes[i];
expose(v, true);
return v;
}

template &lt;typename... T&gt;
void Apply(int i, T... args) {
node* v = nodes[i];
splay_tree::Apply(v, args...);
}
};

int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin &gt;&gt; n &gt;&gt; m;
link_cut_tree&lt;true&gt; lct(n);
vector&lt;vector&lt;pair&lt;int, int&gt;&gt;&gt; g(n);
for (int i = 0; i &lt; n - 1; i++) {
    int x, y, z;
    cin &gt;&gt; x &gt;&gt; y &gt;&gt; z;
--x; --y;
g[x].emplace_back(y, z);
}
vector&lt;long long&gt; dist(n, 0);
vector&lt;int&gt; pv(n, -1);
function&lt;void(int)&gt; Dfs = [&amp;](int v) {
lct.expose(lct.nodes[v]);
for (auto&amp; p : g[v]) {
int u = p.first;
pv[u] = v;
dist[u] = dist[v] + p.second;
lct.link(u, v);
Dfs(u);
}
};
Dfs(0);
vector&lt;int&gt; s(m), t(m);
vector&lt;pair&lt;long long, long long&gt;&gt; segs;
for (int i = 0; i &lt; m; i++) {
    cin &gt;&gt; s[i] &gt;&gt; t[i];
--s[i];
lct.expose(lct.nodes[s[i]]);
auto check = lct.check;
debug(check);
for (int v : check) {
lct.expose(lct.nodes[v]);
long long val = lct.nodes[v]-&gt;val;
long long last_time = (val == 0 ? 0 : val + dist[v]);
long long until = t[i] + dist[v];
segs.emplace_back(last_time + 1, until);
}
lct.expose(lct.nodes[s[i]]);
lct.nodes[s[i]]-&gt;push();
auto nd = lct.nodes[s[i]]-&gt;l;
if (nd != nullptr) {
nd-&gt;unsafe_Apply(t[i]);
}
}
sort(segs.begin(), segs.end());
debug(segs);
multiset&lt;long long&gt; rs;
vector&lt;long long&gt; done;
long long ans = -1;
for (int it = 0; it &lt; (int) segs.size(); it++) {
    rs.emplace(segs[it].second);
    long long until = (it == (int) segs.size() - 1 ? (long long) 9e18 : segs[it + 1].first);
    long long now = segs[it].first;
    while (!rs.empty() &amp;&amp; now &lt; until) {
      auto iter = rs.begin();
      if (now &gt; *iter) {
ans = *iter;
break;
}
done.push_back(*iter);
now += 1;
rs.erase(iter);
}
}
long long cc = 0;
for (long long x : done) {
if (x &lt; ans || ans == -1) {
      ++cc;
    }
  }
  cout &lt;&lt; ans &lt;&lt; " " &lt;&lt; cc &lt;&lt; '\n';
  return 0;
}