This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/GRL_2_B"
#include <iostream>
#include "C++/graph/mst/directed.hpp"
int main() {
int v, e, r;
std::cin >> v >> e >> r;
std::vector<man::edge> edges;
while(e--) {
int s, t, w;
std::cin >> s >> t >> w;
edges.emplace_back(s, t, -1, w);
}
std::cout << man::directed(edges, v, r).cost << '\n';
}
#line 1 "test/directed.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/GRL_2_B"
#include <iostream>
#line 2 "C++/graph/mst/directed.hpp"
#include <ranges>
#line 2 "C++/graph/mst/MST.hpp"
#include <vector>
#line 2 "C++/graph/edge.hpp"
#ifndef EDGE
#define EDGE
#endif
namespace man {
struct edge {
int src, to, id;
long long cost;
edge(){}
edge(const int src_, const int to_, const int id_ = -1, const long long cost_ = 0): src(src_), to(to_), id(id_), cost(cost_){}
constexpr inline operator int() const noexcept { return to; }
};
}
/**
* @brief Edge
*/
#line 5 "C++/graph/mst/MST.hpp"
struct MST {
std::vector<man::edge> tree;
long long cost;
};
/**
* @brief 最小全域木
*/
#line 2 "C++/other/SkewHeap.hpp"
#pragma GCC diagnostic ignored "-Wreorder"
#include <cassert>
#include <algorithm>
namespace man {
namespace internal {
template <bool is_min = true> struct SkewHeap {
struct Node {
long long key, lazy;
Node *l, *r;
int idx;
explicit Node(const long long &key, const int idx): key(key), idx(idx), lazy(0), l(nullptr), r(nullptr){}
};
private:
Node *alloc(const long long &key, int idx = -1) {
return new Node(key, idx);
}
Node *propagate(Node *t) {
if(t && t -> lazy != 0) {
if(t -> l) {
t -> l -> lazy += t -> lazy;
}
if(t -> r) {
t -> r -> lazy += t -> lazy;
}
t -> key += t -> lazy;
t -> lazy = 0;
}
return t;
}
public:
SkewHeap(){}
Node *meld(Node *x, Node *y) {
propagate(x), propagate(y);
if(!x || !y) {
return x ? x : y;
}
if((x -> key < y -> key) ^ is_min) {
std::swap(x, y);
}
x -> r = meld(y, x -> r);
std::swap(x -> l, x -> r);
return x;
}
Node *push(Node *t, const long long &key, int idx = -1){ return meld(t, alloc(key, idx)); }
Node *pop(Node *t) {
assert(t);
return meld(t -> l, t -> r);
}
Node *add(Node *t, const long long &lazy) {
if(t) {
t -> lazy += lazy;
propagate(t);
}
return t;
}
};
}
}
/**
* @brief SkewHeap
* @see https://ei1333.github.io/library/structure/heap/skew-heap.hpp
*/
#line 6 "C++/graph/mst/directed.hpp"
namespace man {
inline MST directed(std::vector<man::edge> edges, const int n, const int v) noexcept {
for(const auto i: std::views::iota(0, n)) {
if(i != v) {
edges.emplace_back(i, v, 0);
}
}
int x = 0;
std::vector<int> par(2 * n, -1), vis(par), link(par), st;
using Node = typename internal::SkewHeap<>::Node;
internal::SkewHeap heap;
std::vector<Node*> ins(2 * n, nullptr);
for(const auto i: std::views::iota(0, std::ssize(edges))) {
const auto &e = edges[i];
ins[e] = heap.push(ins[e], e.cost, i);
}
const auto go = [&](int z) -> int {
z = edges[ins[z]->idx].src;
while(link[z] != -1) {
st.emplace_back(z);
z = link[z];
}
for(const auto &p: st) {
link[p] = z;
}
st.clear();
return z;
};
for(int i = n; ins[x] != 0; ++i) {
while(vis[x] == -1) {
vis[x] = 0;
x = go(x);
}
while(x != i) {
const auto w = ins[x] -> key;
auto z = heap.pop(ins[x]);
z = heap.add(z, -w);
ins[i] = heap.meld(ins[i], z);
par[x] = i;
link[x] = i;
x = go(x);
}
while(ins[x] && go(x) == x) {
ins[x] = heap.pop(ins[x]);
}
}
for(int i = v; i != -1; i = par[i]) {
vis[i] = 1;
}
long long cost = 0;
std::vector<man::edge> e;
for(int i = x; i >= 0; i--) {
if(vis[i] == 1) {
continue;
}
cost += edges[ins[i] -> idx].cost;
e.emplace_back(edges[ins[i] -> idx]);
for(int j = edges[ins[i] -> idx]; j != -1 && vis[j] == 0; j = par[j]) {
vis[j] = 1;
}
}
return {e, cost};
}
}
/**
* @brief Directed MST
* @see https://ei1333.github.io/library/graph/mst/directed-mst.hpp
*/
#line 4 "test/directed.test.cpp"
int main() {
int v, e, r;
std::cin >> v >> e >> r;
std::vector<man::edge> edges;
while(e--) {
int s, t, w;
std::cin >> s >> t >> w;
edges.emplace_back(s, t, -1, w);
}
std::cout << man::directed(edges, v, r).cost << '\n';
}