Problem:
C: Road and Telepoter
問題
N
個の街があり、最初街と街の間に道はありません。
M
個の道候補、
A
個の制限のないテレポーター、
B
個の制限のあるテレポーターがあります。
道
i
を建設すると街
u_i
と街
v_i
を双方向に移動できるようになります。道
i
のコストは
w_i
です。

制限のないテレポーターはある街のペアを選んで、双方向に移動できるようにします。コストは
C
です。

制限のあるテレポーターはある街のペア
i,j
を選んで、
i
から
j
に移動できるようにします。コストは
D
です。
0
以上
N
未満の全ての
i,j
のペアについて、街
i
から
0
回以上移動することで街
j
に移動できるようにするために必要なコストの最小値を出力してください。

ただし、条件を達成できない場合は
-1
を出力してください。
入力形式
N
M
A
B
u_0
v_0
w_0
u_1
v_1
w_1
...
u_{M-1}
v_{M-1}
w_{M-1}
C
D
制約
1\leq N,A,B\leq 10^5
0\leq M\leq
min
(2\times 10^5,N\times (N-1)/2)
1\leq w_i,C,D\leq 10^9
0\leq u_i \lt v_i \lt N
入力はすべて整数
出力形式
条件を達成するのに必要なコストの最小値を出力してください。ただし、条件を達成できない場合は
-1
を出力してください。
入力例1
6 4 1 10
0 2 5
0 4 10
2 3 1
2 4 5
1 2
出力例1
10
入力例2
9 2 2 4
3 7 4
5 7 7
9 2
出力例2
-1

Submitted solutions:

code_snippet: // AOJ #3195
// Road and Telepoter 2025.2.6

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const ll INF = 1LL << 60;
 
// エッジ構造体
struct Edge { int u, v; ll w; };
 
// Union-Find（Disjoint Set Union）
struct DSU {
    vector<int> parent;
    DSU(int n) {
        parent.resize(n);
        for (int i=0; i<n; i++) parent[i] = i;
    }
    int find(int a) {
        if(parent[a] == a) return a;
        return parent[a] = find(parent[a]);
    }
    bool merge(int a, int b) {
        a = find(a); b = find(b);
        if(a == b) return false;
        parent[b] = a;
        return true;
    }
};
 
ll A_param, B_param, C_param, D_param;

ll f_tele(int k) {
    if(k == 1) return 0;
    ll best = INF;
    if(k - 1 <= A_param) {
        best = min(best, (ll)(k - 1) * C_param);
    }
    int r_low = max(0, k - (int)B_param);
    int r_high = min(k, (int)A_param);
    if(r_low <= r_high) {
        int best_r;
        if(C_param >= D_param) best_r = r_low;
        else best_r = r_high;
        ll cand = (ll)best_r * C_param + (ll)(k - best_r) * D_param;
        best = min(best, cand);
    }
    return best;
}
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N, M;
    int A, B;
    cin >> N >> M >> A >> B;
    A_param = A; B_param = B;
    vector<Edge> edges;
    edges.reserve(M);
    for (int i = 0; i < M; i++){
        Edge e;
        cin >> e.u >> e.v >> e.w;
        edges.push_back(e);
    }
    cin >> C_param >> D_param;
 
    // 1. 候補道路から MST 森（各連結成分内での最小全域森）を作る
    sort(edges.begin(), edges.end(), [](const Edge &a, const Edge &b){
        return a.w < b.w;
    });
    DSU dsu(N);
    ll roadCostTotal = 0;
    vector<ll> usedEdges;
    for(auto &e : edges){
        if(dsu.merge(e.u, e.v)){
            roadCostTotal += e.w;
            usedEdges.push_back(e.w);
        }
    }
    int comp0 = 0;
    vector<int> compMarker(N, 0);
    for (int i = 0; i < N; i++){
        int r = dsu.find(i);
        compMarker[r] = 1;
    }
    for (int i = 0; i < N; i++){
        if(compMarker[i] == 1) comp0++;
    }
 
    sort(usedEdges.begin(), usedEdges.end(), greater<ll>());
    int L = usedEdges.size();
    vector<ll> prefix(L+1, 0);
    for (int i = 0; i < L; i++){
        prefix[i+1] = prefix[i] + usedEdges[i];
    }
 
    ll ans = INF;
    for (int r = 0; r <= L; r++){
        int comp = comp0 + r;
        ll teleCost = f_tele(comp);
        if(teleCost >= INF) continue;
        ll total = (roadCostTotal - prefix[r]) + teleCost;
        ans = min(ans, total);
    }
     if(ans >= INF) cout << -1 << endl;
    else cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 7092
final_rank: 7

code_snippet: // AOJ #3195
// Road and Telepoter 2025.2.6

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const ll INF = 1LL << 60;
 
// エッジ構造体
struct Edge { int u, v; ll w; };
 
// Union-Find（Disjoint Set Union）
struct DSU {
    vector<int> parent;
    DSU(int n) {
        parent.resize(n);
        for (int i=0; i<n; i++) parent[i] = i;
    }
    int find(int a) {
        if(parent[a] == a) return a;
        return parent[a] = find(parent[a]);
    }
    bool merge(int a, int b) {
        a = find(a); b = find(b);
        if(a == b) return false;
        parent[b] = a;
        return true;
    }
};
 
ll A_param, B_param, C_param, D_param;

ll f_tele(int k) {
    if(k == 1) return 0;
    ll best = INF;
    if(k - 1 <= A_param) {
        best = min(best, (ll)(k - 1) * C_param);
    }
    int r_low = max(0, k - (int)B_param);
    int r_high = min(k, (int)A_param);
    if(r_low <= r_high) {
        int best_r;
        if(C_param >= D_param) best_r = r_low;
        else best_r = r_high;
        ll cand = (ll)best_r * C_param + (ll)(k - best_r) * D_param;
        best = min(best, cand);
    }
    return best;
}
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int N, M;
    int A, B;
    cin >> N >> M >> A >> B;
    A_param = A; B_param = B;
    vector<Edge> edges;
    edges.reserve(M);
    for (int i = 0; i < M; i++){
        Edge e;
        cin >> e.u >> e.v >> e.w;
        edges.push_back(e);
    }
    cin >> C_param >> D_param;
 
    // 1. 候補道路から MST 森（各連結成分内での最小全域森）を作る
    sort(edges.begin(), edges.end(), [](const Edge &a, const Edge &b){
        return a.w < b.w;
    });
    DSU dsu(N);
    ll roadCostTotal = 0;
    vector<ll> usedEdges;
    for(auto &e : edges){
        if(dsu.merge(e.u, e.v)){
            roadCostTotal += e.w;
            usedEdges.push_back(e.w);
        }
    }
    int comp0 = 0;
    vector<int> compMarker(N, 0);
    for (int i = 0; i < N; i++){
        int r = dsu.find(i);
        compMarker[r] = 1;
    }
    for (int i = 0; i < N; i++){
        if(compMarker[i] == 1) comp0++;
    }
 
    sort(usedEdges.begin(), usedEdges.end(), greater<ll>());
    int L = usedEdges.size();
    vector<ll> prefix(L+1, 0);
    for (int i = 0; i < L; i++){
        prefix[i+1] = prefix[i] + usedEdges[i];
    }
 
    ll ans = INF;
    for (int r = 0; r <= L; r++){
        int comp = comp0 + r;
        ll teleCost = f_tele(comp);
        if(teleCost >= INF) continue;
        ll total = (roadCostTotal - prefix[r]) + teleCost;
        ans = min(ans, total);
    }
     if(ans >= INF) cout << -1 << endl;
    else cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 7372
final_rank: 8

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

struct UnionFind{
    vector<int> par,num;
    UnionFind(int n):par(n),num(n,1){
        iota(par.begin(),par.end(),0);  //include<numeric>
    }
    int find(int v){
        return (par[v]==v)?v:(par[v]=find(par[v]));
    }
    void unite(int u,int v){
        u=find(u),v=find(v);
        if(u==v)return;
        if(num[u]<num[v])swap(u,v);
        num[u]+=num[v];
        par[v]=u;
    }
    bool same(int u,int v){
        return find(u) == find(v);
    }
    int size(int v){
        return num[find(v)];
    }
};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m; cin >> n >> m;
    int A,B; cin >> A >> B;
    vector<pair<int,pair<int,int>>> v(m);
    for (int i = 0; i < m; ++i) {
        int x,y,z; cin >> x >> y >> z;
        v[i] = {z, {x, y}};
    }
    ll C,D; cin >> C >> D;
    sort(v.begin(), v.end());
    UnionFind uf(n);
    ll res = 1e18;
    int rem = n;
    auto slv = [&]() -> ll {
        ll res = 1e18;
        if (rem-1 <= A) {
            res = min(res, C*(rem-1));
        }
        else if (rem-A <= B) {
            res = min(res, C*A + D*(rem-A));
        }
        if (rem <= B) {
            res = min(res, D*rem);
        }
        else if (rem-B+1-1 <= A) {
            res = min(res, D*B + C*(rem-B));
        }
        return res;
    };
    ll cost = 0;
    res = min(res, slv());
    for (auto p : v) {
        if (!uf.same(p.second.first, p.second.second)) {
            cost += p.first;
            uf.unite(p.second.first, p.second.second);
            rem -= 1;
            res = min(res, cost+slv());
        }
    }
    if (res == 1e18) res = -1;
    cout << res << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 5548
final_rank: 4

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 3195.cc: Road and Telepoter
 */

#include<cstdio>
#include<vector>
#include<algorithm>
 
using namespace std;

/* constant */

const int MAX_N = 100000;
const int MAX_M = 200000;
const long long LINF = 1LL << 62;

/* typedef */

typedef long long ll;

struct Edge {
  int u, v, w;
  Edge() {}
  Edge(int _u, int _v, int _w): u(_u), v(_v), w(_w) {}
  void read() { scanf("%d%d%d", &u, &v, &w); }
  bool operator<(const Edge &e) const { return w < e.w; }
};

struct UFT {
  vector<int> links, ranks, sizes;
  UFT() {}

  void init(int n) {
    links.resize(n);
    for (int i = 0; i < n; i++) links[i] = i;
    ranks.assign(n, 1);
    sizes.assign(n, 1);
  }

  int root(int i) {
    int i0 = i;
    while (links[i0] != i0) i0 = links[i0];
    return (links[i] = i0);
  }

  int rank(int i) { return ranks[root(i)]; }
  int size(int i) { return sizes[root(i)]; }
  bool same(int i, int j) { return root(i) == root(j); }

  int merge(int i0, int i1) {
    int r0 = root(i0), r1 = root(i1), mr;
    if (r0 == r1) return r0;
    if (ranks[r0] == ranks[r1]) {
      links[r1] = r0;
      sizes[r0] += sizes[r1];
      ranks[r0]++;
      mr = r0;
    }
    else if (ranks[r0] > ranks[r1]) {
      links[r1] = r0;
      sizes[r0] += sizes[r1];
      mr = r0;
    }
    else {
      links[r0] = r1;
      sizes[r1] += sizes[r0];
      mr = r1;
    }
    return mr;
  }
};

/* global variables */

Edge es[MAX_M];
UFT uft;

/* subroutines */

ll additional(int k, int a, int b, int c, int d) {
  ll f = 0;
  if (k > 1) {
    int a0 = min(k - 1, a), b0 = k - a0;
    if (b0 == 1) b0 = 0;
    ll f0 = (b0 <= b) ? (ll)c * a0 + (ll)d * b0 : LINF;
    
    int b1 = min(k, b), a1 = k - b1;
    ll f1 = (a1 <= a) ? (ll)c * a1 + (ll)d * b1 : LINF;

    f = min(f0, f1);
  }
  //printf("additiona(%d) = %lld\n", k, f);
  return f;
}

/* main */

int main() {
  int n, m, a, b;
  scanf("%d%d%d%d", &n, &m, &a, &b);
  if (b == 1) b = 0;
  
  for (int i = 0; i < m; i++) es[i].read();
  sort(es, es + m);

  int c, d;
  scanf("%d%d", &c, &d);

  uft.init(n);
  int k = n;
  ll minsum = additional(k, a, b, c, d), sum = 0;

  for (int i = 0; k > 1 && i < m; i++) {
    Edge &e = es[i];
    if (! uft.same(e.u, e.v)) {
      sum += e.w;
      uft.merge(e.u, e.v);
      k--;
    }
    //printf("k=%d, sum=%lld\n", k, sum);

    ll f = additional(k, a, b, c, d);
    if (f < LINF)
      minsum = min(minsum, sum + f);
  }

  printf("%lld\n", (minsum < LINF) ? minsum : -1LL);

  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 5364
final_rank: 1

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

using namespace std;

typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;


#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()

#define MOD 1000000007

template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-9, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt< 1000000007 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;

  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }

  inline T fact(int k) const { return _fact[k]; }

  inline T rfact(int k) const { return _rfact[k]; }

  inline T inv(int k) const { return _inv[k]; }

  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }

  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }

  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
struct UnionFind{
  vector<int> par;
  vector<int> siz;

  UnionFind(int sz_): par(sz_), siz(sz_) {
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  void init(int sz_){
    par.resize(sz_);
    siz.resize(sz_);
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  int root(int x){
    if(x == par[x]) return x;
    return par[x] = root(par[x]);
  }

  bool merge(int x, int y){
    x = root(x), y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(int x, int y){
    return root(x) == root(y);
  }

  int size(int x){
    return siz[root(x)];
  }
};
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);
  
  ll N, M, A, B;
  cin >> N >> M >> A >> B;
  vector<bool> used(M,false);
  vector<int> u(M), v(M), w(M);
  vector<pair<int, pair<int, int>>> g;
  REP(i,M){
    cin >> u[i] >> v[i] >> w[i];
    g.push_back({w[i],{u[i],v[i]}});
  }
  sort(all(g));
  ll C, D; cin >> C >> D;
  UnionFind uf(N);
  ll ans = (1LL<<60);
  if(A >= N-1) {
    ans = min(ans, C * (N-1));
  }
  if(B >= N) {
    ans = min(ans, D * N);
  }
  vector<ll> t;
  REP(i,A){
    t.push_back(C);
  }
  REP(i,B-2){
    t.push_back(D);
  }
  sort(all(t));
  vector<ll> cums(t.size()+1);
  REP(i,t.size()){
    cums[i+1] = cums[i] + t[i];
  }
  if(B >= 2 && A+B >= N){
    ans = min(ans, D*2 + cums[N-2]);
  }

  ll tmp = 0;
  int comp = N;
  REP(i,M){
    int a, b;
    tie(a, b) = g[i].second;
    int cost = g[i].first;
    if(!uf.issame(a, b)) {
      tmp += cost;
      uf.merge(a, b);
      comp--;
    }
    if(A >= comp-1) {
      ans = min(ans, tmp + C*(comp-1));
    }
    if(B >= comp) {
      ans = min(ans, tmp + D*comp);
    }
    if(B>=2 && A+B >= comp) {
      ans = min(ans, tmp + D*2 + cums[max(0,comp-2)]);
    }
  }

  if(ans == (1LL<<60)) ans = -1;
  cout << ans << endl;
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 9624
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int MOD = 1e9 + 7;

int Root(int x, vector<int> &root)
{
    if (x == root[x]) return x;
    return root[x] = Root(root[x], root);
}

int Merge(int v, int u, vector<int> &root, vector<int> &sz)
{
    v = Root(v, root), u = Root(u, root);
    if (v == u) return 0;
    if (sz[v] > sz[u]) swap(v, u);
    sz[u] += sz[v];
    root[v] = u;
    return 1;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    long long ans = 1e18;

    int n, m, a, b;
    cin >> n >> m >> a >> b;
    struct edge{
        int v, u, w;
    };
    vector<edge> e(m);
    for (int i = 0; i < m; i++)
    {
        cin >> e[i].v >> e[i].u >> e[i].w;
    }
    int c, d;
    cin >> c >> d;
    for (int i = 0; i < a; i++)
    {
        e.push_back({-1, -1, c});
    }
    sort(e.begin(), e.end(), [&](edge A, edge B){
         return A.w < B.w;
         });
    long long cur = 0;
    vector<int> root(n), sz(n, 1);
    for (int i = 0; i < n; i++) root[i] = i;
    int comp = n;
    if (comp == 1) 
        comp = 0;
    if (comp <= b)
        ans = min(ans, 1ll * comp * d);
    for (auto it : e)
    {
        if (it.v == -1)
        {
            comp--;
            cur += it.w;
        }
        else
        {
            if (Merge(it.v, it.u, root, sz))
                comp--, cur += it.w;
        }
        if (comp == 1)
            comp = 0;
        if (comp <= b)
        {
            //cout << cur << " " << comp << " " << d << endl;
            ans = min(ans, cur + 1ll * max(0, comp) * d);
        }
    }

    if (ans == 1e18)
        cout << -1 << endl;
    else
        cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 8944
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int MOD = 1e9 + 7;

int Root(int x, vector<int> &root)
{
    if (x == root[x]) return x;
    return root[x] = Root(root[x], root);
}

int Merge(int v, int u, vector<int> &root, vector<int> &sz)
{
    v = Root(v, root), u = Root(u, root);
    if (v == u) return 0;
    if (sz[v] > sz[u]) swap(v, u);
    sz[u] += sz[v];
    root[v] = u;
    return 1;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    long long ans = 1e18;

    int n, m, a, b;
    cin >> n >> m >> a >> b;
    struct edge{
        int v, u, w;
    };
    vector<edge> e(m);
    for (int i = 0; i < m; i++)
    {
        cin >> e[i].v >> e[i].u >> e[i].w;
    }
    int c, d;
    cin >> c >> d;
    for (int i = 0; i < a; i++)
    {
        e.push_back({-1, -1, c});
    }
    sort(e.begin(), e.end(), [&](edge A, edge B){
         return A.w < B.w;
         });
    long long cur = 0;
    vector<int> root(n), sz(n, 1);
    for (int i = 0; i < n; i++) root[i] = i;
    int comp = n;
    if (comp == 1) 
        comp = 0;
    if (comp <= b)
        ans = min(ans, 1ll * comp * d);
    for (auto it : e)
    {
        if (it.v == -1)
        {
            comp--;
            cur += it.w;
        }
        else
        {
            if (Merge(it.v, it.u, root, sz))
                comp--, cur += it.w;
        }
        if (comp == 1)
            comp = 0;
        if (comp <= b)
        {
            //cout << cur << " " << comp << " " << d << endl;
            ans = min(ans, cur + 1ll * max(0, comp) * d);
        }
    }

    if (ans == 1e18)
        cout << -1 << endl;
    else
        cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 8952
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005

struct Edge{
	bool operator<(const struct Edge &arg) const{

		return cost < arg.cost;
	}
	int from,to;
	ll cost;
};

int N,M;
ll A,B,cost_A,cost_B;
int boss[SIZE],height[SIZE];
Edge edge[2*SIZE];


int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	if(boss_x == boss_y)return;

	if(height[boss_x] > height[boss_y]){

		boss[boss_y] = boss_x;

	}else if(height[boss_x] < height[boss_y]){

		boss[boss_x] = boss_y;

	}else{ //height[boss_x] == height[boss_y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

ll calc(int rest){

	ll ret = 0;

	if(cost_A <= cost_B){

		if(rest <= A){

			ret += cost_A*rest;
		}else{ //rest > A

			ret += cost_A*A;
			rest -= A;
			ret += cost_B*(rest+1);
		}

	}else{ // costA > cost_B

		if((A >= rest  && B >= rest+1 && cost_A*rest < cost_B*(rest+1)) ||
				(A >= rest  && B <= rest && cost_A*rest < cost_B*(B)+cost_A*(rest-(B-1)))){

			ret += cost_A*rest;
		}else{

			if(B >= rest+1){

				ret += cost_B*(rest+1);
			}else{

				ret += cost_B*B;
				rest -= (B-1);

				ret += cost_A*rest;
			}
		}
	}

	return ret;
}

int main(){

	scanf("%d %d %lld %lld",&N,&M,&A,&B);

	for(int i = 0; i < M; i++){

		scanf("%d %d %lld",&edge[i].from,&edge[i].to,&edge[i].cost);
	}
	sort(edge,edge+M);

	scanf("%lld %lld",&cost_A,&cost_B);

	for(int i = 0; i < N; i++){

		boss[i] = i;
		height[i] = 0;
	}

	int rest = N-1;
	ll ans = 0;

	for(int i = 0; i < M; i++){

		if(isSame(edge[i].from,edge[i].to))continue;

		if(edge[i].cost <= min(cost_A,cost_B)){

			unite(edge[i].from,edge[i].to);
			ans += edge[i].cost;
			rest--;

			//printf("%d-%dを%lldでunite\n",edge[i].from,edge[i].to,edge[i].cost);

		}else{

			if(rest > A+B-1){ //使わざるを得ない

				unite(edge[i].from,edge[i].to);
				ans += edge[i].cost;
				rest--;
				continue;
			}

			//使った場合のコスト
			ll use_cost = edge[i].cost+calc(rest-1);

			//使わなかった場合のコスト
			ll not_cost = calc(rest);

			if(use_cost < not_cost){

				unite(edge[i].from,edge[i].to);
				ans += edge[i].cost;
				rest--;
			}else{

				ans += not_cost;
				printf("%lld\n",ans);
				return 0;
			}
		}
	}

	if(rest > A+B-1){

		printf("-1\n");
		return 0;
	}else{

		if(cost_A <= cost_B){

			if(rest <= A){

				ans += cost_A*rest;
			}else{ //rest > A

				ans += cost_A*A;
				rest -= A;
				ans += cost_B*(rest+1);
			}

		}else{ // costA > cost_B

			if((A >= rest  && B >= rest+1 && cost_A*rest < cost_B*(rest+1)) ||
					(A >= rest  && B <= rest && cost_A*rest < cost_B*(B)+cost_A*(rest-(B-1)))){

				ans += cost_A*rest;
			}else{

				if(B >= rest+1){

					ans += cost_B*(rest+1);
				}else{

					ans += cost_B*B;
					rest -= (B-1);

					ans += cost_A*rest;
				}
			}
		}

		printf("%lld\n",ans);
		return 0;
	}

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 6664
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
constexpr ll MAX = 1e6;
struct node {
    ll cost, u, v;
};

class UnionFind {
    int v[MAX] = {};
    int deep[MAX];

  public:
    UnionFind() {
        for(int i = 1; i < MAX; i++) {
            v[i] = i;
            deep[i] = 0;
        }
    }

    int root(int x) {
        if(v[x] == x)
            return x;
        else
            return v[x] = root(v[x]);
    }

    bool same(int x, int y) {
        return (root(x) == root(y));
    }

    void unite(int x, int y) {
        x = root(x);
        y = root(y);
        if(deep[x] > deep[y]) {
            v[y] = x;
        } else {
            if(deep[x] == deep[y]) {
                deep[y]++;
            }
            v[x] = y;
        }
        return;
    }
};

int main() {
    ll N, M, A, B;
    cin >> N >> M >> A >> B;
    vector<node> p(M);
    for(int i = 0; i < M; i++) {
        ll u, v, cost;
        cin >> u >> v >> cost;
        p[i] = {cost, u, v};
    }
    sort(p.begin(), p.end(), [](node &x, node &y) {
        return x.cost < y.cost;
    });
    ll C, D;
    cin >> C >> D;
    UnionFind uf;
    ll ret = 1e18;
    ll road_cnt = 0;
    ll road_cost = 0;

    if(N-1 <= A){//Aのみ
        ret = min(ret , (N-1)*C);
    }
    if(N <= A+B){//B使うとき
        ll need = N - 2;
        ll cost = 2*D;
        ll a = A,b = B-2,c = C,d = D;
        if(c>d){
            swap(a,b);
            swap(c,d);
        }
        cost += min(need,a)*c;
        need -= a;
        if(need>0){
            cost += need * d;
        }
    }

    //cout << ret << endl;
    for(int i = 0; i < M; i++) {
        if(!uf.same(p[i].u, p[i].v)) {
            uf.unite(p[i].u, p[i].v);
            road_cost += p[i].cost;
            road_cnt++;
        }
        // road_cnt 個道を追加
        // 残り N-1-road_cnt 個をテレポートで補う

        ll sum = 1e18;/*
        if(N - 1 - road_cnt <= A + B) {
            sum = min(A, N - 1 - road_cnt) * C;
            if(N - 1 - A >= 0) {
                sum += (N - 1 - road_cnt - A) * D;
            }
            ret = min(ret, road_cost + sum);
        }
        cout << ret << endl;*/
        if(N-1-road_cnt <= A){//Aのみ
            sum = min(sum , (N-1-road_cnt)*C);
        }
        if(N-road_cnt <= A+B){//B使うとき
            ll need = N - 2 - road_cnt;
            ll cost = 2*D;
            ll a = A,b = B-2,c = C,d = D;
            if(c>d){
                swap(a,b);
                swap(c,d);
            }
            cost += min(need,a)*c;
            need -= a;
            if(need>0){
                cost += need * d;
            }
            sum = min(sum,cost);
        }
        ret = min(ret, road_cost + sum);


    }
    if(ret >= 1e18)ret = -1;
    cout << ret << endl;
    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 15072
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }
using ll = long long;
using P = pair<ll, ll>;
const long double PI = acos(-1.0L);
ll GCD(ll a, ll b) { return b?GCD(b, a%b):a; }
ll LCM(ll a, ll b) { return a/GCD(a, b)*b; }

ll n, m, a, b;
ll c, d;
struct road {
    ll u, v, w;
    bool operator<(const road &r) const { return w < r.w; };
};

const ll INF = 1e18;

// UnionFind
struct UnionFind {
    vector<int> d;
    UnionFind(int n=0): d(n,-1) {}

    // ある要素がどの集合に属しているかを返す
    int find(int x) {
      if (d[x] < 0) return x;
      return d[x] = find(d[x]);
    }

    // 集合をマージする、すでに同じ集合ならfalseが返る
    bool unite(int x, int y) {
      x = find(x); y = find(y);
      if (x == y) return false;
      if (d[x] > d[y]) swap(x,y);
      d[x] += d[y];
      d[y] = x;
      return true;
    }

    // 2つの要素が同じ集合か判定する
    bool same(int x, int y) { return find(x) == find(y);}
  
    // ある集合の大きさを答える
    int size(int x) { return -d[find(x)];}
};

int main() {
    cin >> n >> m >> a >> b;
    vector<road> path;
    for(int i = 0; i < m; ++i) {
        road indata;
        cin >> indata.u >> indata.v >> indata.w;
        path.emplace_back(indata);
    }
    cin >> c >> d;

    UnionFind uf(n);
    // 道を低コストから貪欲
    sort(path.begin(), path.end());

    ll ans = INF;
    // 道を1本も使わないとき
    if(a >= n-1) chmin(ans, c*(n-1));   // 無向辺だけで構築
    if(b >= n) chmin(ans, d*n);         // 有向辺だけで構築
    // 無向辺と有向辺合わせて構築
    if(a+b >= n) {
        chmin(ans, c*a+d*max(0LL, n-a));
        chmin(ans, c*max(0LL, n-b)+d*b);
    }

    ll ufs = n;
    ll now = 0;     // 道だけのコストが計算されている
    for(int i = 0; i < m; ++i) {
        if(!uf.same(path[i].u, path[i].v)) {
            uf.unite(path[i].u, path[i].v);
            now += path[i].w;
            ufs--;
        }

        if(ufs >= 2) {
            if(a >= ufs-1) chmin(ans, now+c*(ufs-1));
            if(b >= ufs) chmin(ans, now+d*ufs);
            if(a+b >= ufs) {
                chmin(ans, now+c*a+d*max(0LL, ufs-a));
                chmin(ans, now+c*max(0LL, ufs-b)+d*b);
            }
        }else chmin(ans, now);
    }

    if(ans == INF) cout << -1 << endl;
    else cout << ans << endl;
}
accuracy: 1
time_ms: 130
memory_kb: 9188
final_rank: 15

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

const long long INF = 1e18;
//const ll mod = 1000000007;
ll N, M, A, B;
ll u[201000], v[201000], w[201000];
ll C, D;
ll ans = INF;
ll base = 0;
ll connected;
struct UnionFind {
    vector<int> par;
    vector<int> rank;
    vector<ll> Size;
    UnionFind(int n = 1) {
        init(n);
    }

    void init(int n = 1) {
        par.resize(n + 1); rank.resize(n + 1); Size.resize(n + 1);
        for (int i = 0; i <= n; ++i) par[i] = i, rank[i] = 0, Size[i] = 1;
    }

    int root(int x) {
        if (par[x] == x) {
            return x;
        }
        else {
            int r = root(par[x]);
            return par[x] = r;
        }
    }

    bool issame(int x, int y) {
        return root(x) == root(y);
    }

    bool merge(int x, int y) {
        x = root(x); y = root(y);
        if (x == y) return false;
        if (rank[x] < rank[y]) swap(x, y);
        if (rank[x] == rank[y]) ++rank[x];
        par[y] = x;
        Size[x] += Size[y];
        return true;
    }

    ll size(int x){
        return Size[root(x)];
    }
};


void f() {
    //cerr << connected << " " << base << endl;
    if(connected - 1 <= A) {
        chmin(ans, base + (connected - 1) * C);
    }
    if(connected <= A + B) {
        ll tmpval = 0;
        ll tmpnum;
        if(C < D) {
            tmpnum = min(A, connected);
            tmpval += C * tmpnum;
            tmpval += D * (connected - tmpnum);
        } else {
            tmpnum = min(B, connected);
            tmpval += D * tmpnum;
            tmpval += C * (connected - tmpnum);
        }
        chmin(ans, base + tmpval);
    }
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> N >> M >> A >> B;
    connected = N;
    vector<l_l> a;
    for(int i = 0; i < M; i++) {
        cin >> u[i] >> v[i] >> w[i];
        a.push_back({w[i], i});
    }
    cin >> C >> D;
    f();
    sort(a.begin(), a.end());
    UnionFind uni(N);
    for(auto tmp : a) {
        int idx = tmp.second;
        //cerr << idx << endl;
        if(uni.merge(u[idx], v[idx])) {
            base += w[idx];
            connected--;
            f();
        }
    }
    if(ans == INF) ans = -1;
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 12748
final_rank: 13

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"


using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

class UnionFind {
	vector<int>parent;
	vector<int>rank;
public:
	UnionFind(int num) {
		num++;
		parent.resize(num);
		rank.resize(num);
		for (int i = 0; i < num; i++) {
			parent[i] = i;
			rank[i] = 0;
		}
	}
	int Find(int node) {
		if (parent[node] == node)return node;
		else return parent[node] = Find(parent[node]);
	}
	void Unite(int u, int v) {
		u = Find(u);
		v = Find(v);
		if (u == v)return;
		if (rank[u] < rank[v])parent[u] = v;
		else {
			parent[v] = u;
			if (rank[u] == rank[v])rank[u]++;
		}
	}
	bool Check_Same(int u, int v) {
		return Find(u) == Find(v);
	}
};

struct Edge {
	int a, b, cost;
	bool operator<(const Edge&e)const {
		return cost < e.cost;
	}
};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> N >> M >> L >> R;
	vector<Edge>edge(M);
	for (int i = 0; i < M; i++) {
		cin >> edge[i].a >> edge[i].b >> edge[i].cost;
	}
	sort(edge.begin(), edge.end());
	cin >> H >> W;
	int con = N;
	long long int ans = MOD * MOD;
	UnionFind uf(N);
	long long int box = 0;
	for (auto i : edge) {
		if (uf.Check_Same(i.a, i.b))continue;
		uf.Unite(i.a, i.b);
		box += i.cost;
		con--;
		if (L >= con - 1) {
			ans = min(ans, box + H * (con - 1));
		}
		else if (con - L <= R) {
			ans = min(ans, box + H * L + (con - L)*W);
		}
		if (R >= con) {
			ans = min(ans, box + W * con);
		}
		else if (con - R <= L) {
			ans = min(ans, box + W * R + (con - R)*H);
		}
	}
	if (L >= N - 1) {
		ans = min(ans, H*(N - 1));
	}
	if (R >= N) {
		ans = min(ans, W*N);
	}
	if (ans == MOD * MOD)ans = -1;
	cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 5496
final_rank: 3

code_snippet: #include <iostream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#define llint long long
#define inf 1e18
#define rep(x, s, t) for(llint (x) = (s); (x) < (t); (x)++)
#define Rep(x, s, t) for(llint (x) = (s); (x) <= (t); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))

using namespace std;
typedef pair<llint, llint> P;
typedef pair<llint, P> E;

struct UnionFind{
	int size;
	vector<int> parent;
	
	UnionFind(){}
	UnionFind(int size){
		this->size = size;
		parent.resize(size+1);
		init();
	}
	void init(){
		for(int i = 0; i <= size; i++) parent[i] = i;
	}
	int root(int i){
		if(parent[i] == i) return i;
		return parent[i] = root(parent[i]);
	}
	bool same(int i, int j){
		return root(i) == root(j);
	}
	void unite(int i, int j){
		int root_i = root(i), root_j = root(j);
		if(root_i == root_j) return;
		parent[root_i] = root_j;
	}
};


llint n, m, a, b, c, d;
vector<llint> G[100005];
vector<E> vec;
UnionFind uf(100005);

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n >> m >> a >> b;
	b--;
	b = max(b, 0LL);
	a = min(a, n-1), b = min(b, n-1);
	
	llint u, v, w;
	for(int i = 1; i <= m; i++){
		cin >> u >> v >> w;
		vec.push_back(E(w, P(u, v)));
	}
	sort(vec.begin(), vec.end());
	cin >> c >> d;
	
	vector<llint> avec;
	for(int i = 0; i < vec.size(); i++){
		llint u = vec[i].second.first, v = vec[i].second.second, w = vec[i].first;
		if(uf.same(u, v)) continue;
		avec.push_back(w);
		uf.unite(u, v);
	}
	while(avec.size() < n-1) avec.push_back(inf);
	
	llint ans = inf;
	vector<llint> bvec = avec;
	
	llint p = upper_bound(avec.begin(), avec.end(), c) - avec.begin();
	p = max(p, (llint)avec.size()-a);
	for(int i = 0; i < a; i++){
		if(p+i >= avec.size()) break;
		avec[p+i] = c;
	}
	
	llint sum = 0;
	for(int i = 0; i < avec.size(); i++){
		if(avec[i] > inf/2){
			sum = inf;
			break;
		}
		sum += avec[i];
	}
	ans = min(ans, sum);
	
	avec = bvec;
	
	sum = d;
	p = upper_bound(avec.begin(), avec.end(), c) - avec.begin();
	p = max(p, (llint)avec.size()-(a+b));
	
	if(p == (llint)avec.size()-(a+b)){
		for(int i = 0; i < a; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = c;
		}
		for(int i = 0; i < b; i++){
			if(p+a+i >= avec.size()) break;
			avec[p+a+i] = d;
		}
	}
	else{
		for(int i = 0; i < a; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = c;
		}
		p = upper_bound(avec.begin()+a, avec.end(), d) - avec.begin();
		p = max(p, (llint)avec.size()-b);
		for(int i = 0; i < b; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = d;
		}
	}
	
	for(int i = 0; i < avec.size(); i++){
		if(avec[i] > inf/2){
			sum = inf;
			break;
		}
		sum += avec[i];
	}
	ans = min(ans, sum);
	
	
	avec = bvec;
	
	
	sum = d;
	swap(a, b), swap(c, d);
	p = upper_bound(avec.begin(), avec.end(), c) - avec.begin();
	p = max(p, (llint)avec.size()-(a+b));
	
	if(p == (llint)avec.size()-(a+b)){
		for(int i = 0; i < a; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = c;
		}
		for(int i = 0; i < b; i++){
			if(p+a+i >= avec.size()) break;
			avec[p+a+i] = d;
		}
	}
	else{
		for(int i = 0; i < a; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = c;
		}
		p = upper_bound(avec.begin()+p+a, avec.end(), d) - avec.begin();
		p = max(p, (llint)avec.size()-b);
		for(int i = 0; i < b; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = d;
		}
	}
	
	for(int i = 0; i < avec.size(); i++){
		if(avec[i] > inf/2){
			sum = inf;
			break;
		}
		sum += avec[i];
	}
	ans = min(ans, sum);
	
	
	if(ans > inf/2) cout << -1 << endl;
	else cout << ans << endl;
	
	return 0;
}
accuracy: 0.975
time_ms: 40
memory_kb: 11852
final_rank: 18

code_snippet: #include <iostream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#define llint long long
#define inf 1e18
#define rep(x, s, t) for(llint (x) = (s); (x) < (t); (x)++)
#define Rep(x, s, t) for(llint (x) = (s); (x) <= (t); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))

using namespace std;
typedef pair<llint, llint> P;
typedef pair<llint, P> E;

struct UnionFind{
	int size;
	vector<int> parent;
	
	UnionFind(){}
	UnionFind(int size){
		this->size = size;
		parent.resize(size+1);
		init();
	}
	void init(){
		for(int i = 0; i <= size; i++) parent[i] = i;
	}
	int root(int i){
		if(parent[i] == i) return i;
		return parent[i] = root(parent[i]);
	}
	bool same(int i, int j){
		return root(i) == root(j);
	}
	void unite(int i, int j){
		int root_i = root(i), root_j = root(j);
		if(root_i == root_j) return;
		parent[root_i] = root_j;
	}
};


llint n, m, a, b, c, d;
vector<llint> G[100005];
vector<E> vec;
UnionFind uf(100005);

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n >> m >> a >> b;
	b--;
	b = max(b, 0LL);
	
	llint u, v, w;
	for(int i = 1; i <= m; i++){
		cin >> u >> v >> w;
		vec.push_back(E(w, P(u, v)));
	}
	sort(vec.begin(), vec.end());
	cin >> c >> d;
	
	vector<llint> avec;
	for(int i = 0; i < vec.size(); i++){
		llint u = vec[i].second.first, v = vec[i].second.second, w = vec[i].first;
		if(uf.same(u, v)) continue;
		avec.push_back(w);
		uf.unite(u, v);
	}
	while(avec.size() < n-1) avec.push_back(inf);
	
	llint ans = inf;
	vector<llint> bvec = avec;
	
	llint p = upper_bound(avec.begin(), avec.end(), c) - avec.begin();
	p = max(p, (llint)avec.size()-a);
	for(int i = 0; i < a; i++){
		if(p+i >= avec.size()) break;
		avec[p+i] = c;
	}
	
	llint sum = 0;
	for(int i = 0; i < avec.size(); i++){
		if(avec[i] > inf/2){
			sum = inf;
			break;
		}
		sum += avec[i];
	}
	ans = min(ans, sum);
	
	avec = bvec;
	
	sum = d;
	p = upper_bound(avec.begin(), avec.end(), c) - avec.begin();
	p = max(p, (llint)avec.size()-(a+b));
	
	if(p == (llint)avec.size()-(a+b)){
		for(int i = 0; i < a; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = c;
		}
		for(int i = 0; i < b; i++){
			if(p+a+i >= avec.size()) break;
			avec[p+a+i] = d;
		}
	}
	else{
		for(int i = 0; i < a; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = c;
		}
		p = upper_bound(avec.begin()+a, avec.end(), d) - avec.begin();
		p = max(p, (llint)avec.size()-b);
		for(int i = 0; i < b; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = d;
		}
	}
	
	for(int i = 0; i < avec.size(); i++){
		if(avec[i] > inf/2){
			sum = inf;
			break;
		}
		sum += avec[i];
	}
	ans = min(ans, sum);
	
	
	avec = bvec;
	
	
	sum = d;
	swap(a, b), swap(c, d);
	p = upper_bound(avec.begin(), avec.end(), c) - avec.begin();
	p = max(p, (llint)avec.size()-(a+b));
	
	if(p == (llint)avec.size()-(a+b)){
		for(int i = 0; i < a; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = c;
		}
		for(int i = 0; i < b; i++){
			if(p+a+i >= avec.size()) break;
			avec[p+a+i] = d;
		}
	}
	else{
		for(int i = 0; i < a; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = c;
		}
		p = upper_bound(avec.begin()+p+a, avec.end(), d) - avec.begin();
		p = max(p, (llint)avec.size()-b);
		for(int i = 0; i < b; i++){
			if(p+i >= avec.size()) break;
			avec[p+i] = d;
		}
	}
	
	for(int i = 0; i < avec.size(); i++){
		if(avec[i] > inf/2){
			sum = inf;
			break;
		}
		sum += avec[i];
	}
	ans = min(ans, sum);
	
	
	if(ans > inf/2) cout << -1 << endl;
	else cout << ans << endl;
	
	return 0;
}
accuracy: 0.975
time_ms: 40
memory_kb: 11896
final_rank: 19

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
#include <set>
#include <iomanip>
#include <queue>
#include <string>
#include <map>
#include <fstream>
#include <cassert>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>

class UnionFind {
	std::vector<int> parent;
public:
	UnionFind(const int size) : parent(size, -1) {};
	int find(const int a) {
		return parent[a] < 0 ? a : parent[a] = find(parent[a]);
	}
	bool is_same(const int a, const int b) {
		return find(a) == find(b);
	}
	void unite(int a, int b) {
		a = find(a);
		b = find(b);
		if (a == b) return;
		if (parent[a] > parent[b]) std::swap(a, b);
		parent[a] += parent[b];
		parent[b] = a;
	}
};
struct Road {
	int from, to, cost;
};

long long int min_rest_cost(const int rest, const long long int a, const long long int b, const long long int c, const long long int d) {
	long long int min_cost = LLONG_MAX >> 1;
	if (a >= rest - 1) {
		const auto cost = c * rest - c;
		min_cost = std::min(cost, min_cost);
	}
	if (b >= rest) {
		const auto cost = d * rest;
		min_cost = std::min(cost, min_cost);
	}
	if (a + b >= rest) {
		if (c < d) {
			const auto use_c = std::min<long long int>(rest, a);
			const auto use_d = rest - use_c;
			const auto cost = c * use_c + d * use_d;
			min_cost = std::min(cost, min_cost);
		}
		else {
			const auto use_d = std::min<long long int>(rest, b);
			const auto use_c = rest - use_d;
			const auto cost = c * use_c + d * use_d;
			min_cost = std::min(cost, min_cost);
		}
	}
	return min_cost;
}
int main() {
	int n, m, a, b; std::cin >> n >> m >> a >> b;
	std::vector<Road> roads(m);
	for (auto& r : roads) std::cin >> r.from >> r.to >> r.cost;
	long long int c, d; std::cin >> c >> d;
	std::sort(roads.begin(), roads.end(), [](const Road& a, const Road& b) {return a.cost < b.cost; });
	long long int current_cost{ 0 };
	long long int min_cost{ min_rest_cost(n, a, b, c, d) };
	int rest{ n };
	UnionFind uft(n);
	for (const auto r : roads) {
		if (uft.is_same(r.from, r.to)) continue;
		--rest; uft.unite(r.from, r.to);
		current_cost += r.cost;
		min_cost = std::min(min_cost, current_cost + min_rest_cost(rest, a, b, c, d));
	}
	std::cout << (min_cost == LLONG_MAX >> 1 ? -1 : min_cost) << '\n';
}
accuracy: 1
time_ms: 110
memory_kb: 5480
final_rank: 12

code_snippet: // #include <atcoder/all>
// using namespace atcoder;
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)n; ++i)
#define rrep(i, n) for (int i = (int)n-1; i >= 0; --i)
using namespace std;
using ll = long long;
template<typename T>
inline bool chmax(T& a, const T& b) {
    if (a < b){
        a = b;
        return true;
    }
    return false;
}
template<typename T>
inline bool chmin(T& a, const T& b) {
    if (b < a) {
        a = b;
        return true;
    }
    return false;
}
/**
 * @brief 多次元 vector の作成
 * @author えびちゃん
 */
namespace detail {
    template<typename T, int N>
    auto make_vec(vector<int>& sizes, T const& x) {
        if constexpr (N == 1) {
            return vector(sizes[0], x);
        } else {
            int size = sizes[N-1];
            sizes.pop_back();
            return vector(size, make_vec<T, N-1>(sizes, x));
        }
    }
}
template<typename T, int N>
auto make_vec(int const(&sizes)[N], T const& x = T()) {
    vector<int> s(N);
    for (int i = 0; i < N; ++i) s[i] = sizes[N-i-1];
    return detail::make_vec<T, N>(s, x);
}
__attribute__((constructor))
void fast_io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
}

struct unionfind {
    vector<int> d;
    unionfind(int n) : d(n, -1) {}
    int find(int x) {
        if (d[x] < 0) return x;
        return d[x] = find(d[x]);
    }
    bool unite(int x, int y) {
        x = find(x); y = find(y);
        if (x == y) return false;
        if (d[x] > d[y]) swap(x, y);
        d[x] += d[y];
        d[y] = x;
        return true;
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return -d[find(x)]; }
};

int main() {
    int n, m, a, b;
    cin >> n >> m >> a >> b;
    vector<tuple<int, int, int>> es(m);
    rep(i, m) {
        int u, v, w;
        cin >> u >> v >> w;
        es[i] = {w, u, v};
    }
    int c, d;
    cin >> c >> d;

    sort(es.begin(), es.end());
    
    auto calc = [&](int scc) {
        if (scc == 1) return 0LL;
        int mx = a + (b - 1) * (b >= 2);
        if (scc - mx > 1) return -1LL;
        ll res1 = 0;
        int tmp1 = scc;
        res1 += 1LL * c * min(tmp1 - 1, a);
        tmp1 -= min(tmp1 - 1, a);
        if (tmp1 >= 2) res1 += 1LL * d * tmp1;
        ll res2 = 0;
        int tmp2 = scc;
        res2 += 1LL * d * min(tmp2, b);
        tmp2 -= min(tmp2, b) - 1;
        if (tmp2 >= 2) res2 += 1LL * c * (tmp2 - 1);
        return min(res1, res2);
    };

    int scc = n;
    ll ans = LLONG_MAX;
    ll res = calc(scc);
    if (res != -1) chmin(ans, res);

    unionfind uf(n);
    ll now = 0;
    rep(i, m) {
        auto [w, u, v] = es[i];
        if (!uf.same(u, v)) {
            uf.unite(u, v);
            now += w;
            scc--;
            ll res = calc(scc);
            if (res != -1) chmin(ans, now + res);
        }
    }

    cout << (ans == LLONG_MAX ? -1 : ans) << '\n';
}
accuracy: 1
time_ms: 40
memory_kb: 5492
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#define inf (long long)(1e17)
using namespace std;

struct Unionfind {
  // tree number
  vector<int> par;
  // constructor
  Unionfind(int n = 1) : par(n, -1) {}
  // search root
  int root(int x) {
    if (par[x] < 0) return x;
    return par[x] = root(par[x]);
  }
  // is same?
  bool issame(int x, int y) { return root(x) == root(y); }

  // add
  // already added, return 0
  bool uni(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y) return 0;
    if (par[x] > par[y]) swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return 1;
  }
  int size(int x) { return -par[root(x)]; }
};

struct dat {
  long long u, v, cos;
  bool operator<(const dat& d) const {
    if (cos != d.cos) return cos > d.cos;
    if (u != d.u) return u > d.u;
    return v > d.v;
  }
};

long long n, m, a, b, c, d;
priority_queue<dat> pq, pq2;
Unionfind uf;

long long calc(long long x) {
  long long res = 0;
  long long tmp = min(x, a);
  res += c * tmp;
  x -= tmp;
  tmp = min(x, b);
  res += d * tmp;
  x -= tmp;
  if (x) return inf;
  return res;
}

int main() {
  cin >> n >> m >> a >> b;
  uf = Unionfind(n);
  for (int i = 0; i < m; ++i) {
    int x, y, z;
    cin >> x >> y >> z;
    dat now;
    now.u = x;
    now.v = y;
    now.cos = z;
    pq.push(now);
  }
  cin >> c >> d;
  long long res = inf, cnt = 0, sum = 0;
  if (a >= n - 1) res = (n - 1) * c;
  pq2 = pq;
  while (pq.size()) {
    dat now = pq.top();
    pq.pop();
    if (!uf.issame(now.u, now.v)) {
      ++cnt;
      sum += now.cos;
      uf.uni(now.u, now.v);
    }
    if (a >= n - 1 - cnt) res = min(res, sum + c * (n - 1 - cnt));
  }
  pq = pq2;
  sum = d, cnt = 0;
  --b;
  if (c > d) {
    swap(c, d);
    swap(a, b);
  }
  uf = Unionfind(n);
  while (pq.size()) {
    dat now = pq.top();
    pq.pop();
    if (!uf.issame(now.u, now.v)) {
      ++cnt;
      sum += now.cos;
      uf.uni(now.u, now.v);
    }
    if (a + b >= n - 1 - cnt) res = min(res, sum + calc(n - 1 - cnt));
  }
  if (res == inf)
    cout << -1 << endl;
  else
    cout << res << endl;
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 14048
final_rank: 16

code_snippet: // #include <atcoder/all>
// using namespace atcoder;
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)n; ++i)
#define rrep(i, n) for (int i = (int)n-1; i >= 0; --i)
using namespace std;
using ll = long long;
template<typename T>
inline bool chmax(T& a, const T& b) {
    if (a < b){
        a = b;
        return true;
    }
    return false;
}
template<typename T>
inline bool chmin(T& a, const T& b) {
    if (b < a) {
        a = b;
        return true;
    }
    return false;
}
/**
 * @brief 多次元 vector の作成
 * @author えびちゃん
 */
namespace detail {
    template<typename T, int N>
    auto make_vec(vector<int>& sizes, T const& x) {
        if constexpr (N == 1) {
            return vector(sizes[0], x);
        } else {
            int size = sizes[N-1];
            sizes.pop_back();
            return vector(size, make_vec<T, N-1>(sizes, x));
        }
    }
}
template<typename T, int N>
auto make_vec(int const(&sizes)[N], T const& x = T()) {
    vector<int> s(N);
    for (int i = 0; i < N; ++i) s[i] = sizes[N-i-1];
    return detail::make_vec<T, N>(s, x);
}
__attribute__((constructor))
void fast_io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
}

struct unionfind {
    vector<int> d;
    unionfind(int n = 0) : d(n, -1) {}
    int find(int x) {
        if (d[x] < 0) return x;
        return d[x] = find(d[x]);
    }
    bool unite(int x, int y) {
        x = find(x); y = find(y);
        if (x == y) return false;
        if (d[x] > d[y]) swap(x, y);
        d[x] += d[y];
        d[y] = x;
        return true;
    }
    bool same(int x, int y) { return find(x) == find(y);}
    int size(int x) { return -d[find(x)];}
};

struct edge{ int u, v; long long weight; };
bool comp(const edge& e1, const edge& e2) { return e1.weight < e2.weight; }
vector<edge> es;

vector<ll> kruskal(unionfind& uf) {
    sort(es.begin(), es.end(), comp);
    vector<ll> res;
    for (size_t i = 0; i < es.size(); ++i) {
        edge e = es[i];
        if (!uf.same(e.u, e.v)) {
            uf.unite(e.u, e.v);
            res.push_back(e.weight);
        }
    }
    return res;
}

int main() {
    int n, m, a, b;
    cin >> n >> m >> a >> b;
    rep(i, m) {
        int u, v, w;
        cin >> u >> v >> w;
        es.push_back({u, v, w});
    }
    int c, d;
    cin >> c >> d;

    unionfind uf(n);
    auto es = kruskal(uf);

    int scc = 0;
    rep(i, n) {
        if (uf.find(i) == i) scc++;
    }
    const ll inf = 1e10;
    rep(i, scc-1) es.push_back(inf);
    sort(es.rbegin(), es.rend());
    rep(i, min(a, (int)es.size())) {
        if (es[i] > c) es[i] = c;
        else break;
    }
    sort(es.rbegin(), es.rend());
    ll sum = 0;
    rep(i, es.size()) sum += es[i];
    
    ll ans = LLONG_MAX;
    if (es[0] != inf) chmin(ans, sum);
    rep(i, es.size()) {
        if (i + 2 > b) break;
        sum -= es[i];
        if (i == (int)es.size() - 1 || es[i+1] != inf) {
            ll cost = sum + d * (i + 2);
            chmin(ans, cost);
        }
    }
    cout << (ans == LLONG_MAX ? -1 : ans) << '\n';
}
accuracy: 0.5
time_ms: 20
memory_kb: 5164
final_rank: 20

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double Double;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

class UnionFind {
    std::vector<int> p;

public:
    UnionFind(int n) : p(n, -1) {}

    int root(int x) { return p[x] < 0 ? x : p[x] = root(p[x]); }

    bool same(int x, int y) { return root(x) == root(y); }

    bool unite(int x, int y) {
        x = root(x);
        y = root(y);
        if (x == y) return false;
        if (p[y] < p[x]) std::swap(x, y);
        if (p[x] == p[y]) --p[x];
        p[y] = x;
        return true;
    }
};


long long count(int x, int A, int B, int C, int D) {
    if( x == 1 ){
        return 0;
    }
    long long ans = 1e18;
    for (auto a : {0, x - 1, A}) {
        if( a > A ) continue;
        if( a > x - 1 ) continue;

        int r = x - a;

        if (r == 1) {
            ans = min(ans, 1ll * a * C);
        } else if (r > B) {
            continue;
        } else {
            ans = min(ans, 1ll * a * C + 1ll * r * D);
        }
    }
    for (auto b : {0, B, x}) {
        if( b > B ) continue;
        if( b > x ) continue;

        if (b == 1) continue;
        int r = x - (b - 1);

        if (r - 1 > A) {
            continue;
        }
        ans = min(ans, 1ll * b * D + 1ll * (r - 1) * C);
    }
    return ans;

}

int main() {
    int N, M, A, B;
    cin >> N >> M >> A >> B;


    vector<pair<int, pair<int, int>>> es;
    for (int i = 0; i < M; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        es.push_back({w, {u, v}});
    }
    int C, D;
    cin >> C >> D;

    sort(es.begin(), es.end());

    UnionFind uf(N);
    long long tot = 0;
    long long ans = count(N, A, B, C, D);

    int x = 0;
    for (int i = 0; i < es.size(); i++) {
        if (uf.unite(es[i].second.first, es[i].second.second)) {
            tot += es[i].first;
            x++;
            ans = min(tot + count(N - x, A, B, C, D), ans);
        }
    }
    if( ans >= 1e15 ){
     cout << -1 << endl;
    }else {
        cout << ans << endl;
    }

}
accuracy: 1
time_ms: 130
memory_kb: 5984
final_rank: 14

code_snippet: #include <iostream>
#include <cstdio>
using namespace std;
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) begin(v),end(v)
#define fi first
#define se second
template<typename A, typename B> inline bool chmax(A &a, B b) { if (a<b) { a=b; return 1; } return 0; }
template<typename A, typename B> inline bool chmin(A &a, B b) { if (a>b) { a=b; return 1; } return 0; }
using ll = long long;
using pii = pair<int, int>;
constexpr ll INF = 1ll<<30;
constexpr ll longINF = 1ll<<60;
constexpr ll MOD = 1000000007;
constexpr bool debug = 0;
//---------------------------------//

#include <vector>
#include <numeric>
#include <utility>
#include <cassert>

struct UnionFind {
public:
	using size_type = std::size_t;
	
	UnionFind(size_type n) : n(n), size_(n, 1) {
		par.resize(n);
		std::iota(par.begin(), par.end(), 0);
	}
	
	size_type size(size_type x) { return size_[find(x)]; }
	
	size_type find(size_type x) {
		assert(x < n);
		while (par[x] != x) {
			par[x] = par[par[x]];
			x = par[x];
		}
		return x;
	}
	
	void unite(size_type x, size_type y) {
		x = find(x);
		y = find(y);
		if (x == y) return;
		if (size(x) > size(y)) std::swap(x, y);
		par[x] = y;
		size_[y] += size_[x];
	}
	
	bool issame(size_type x, size_type y) { return find(x) == find(y); }
	
private:
	size_type n;
	std::vector<size_type> size_, par;
};

#include <vector>
#include <algorithm>
#include <numeric>

int main() {
	int N, M, A, B;
	cin >> N >> M >> A >> B;
	
	vector<int> U(M), V(M), W(M);
	REP(i, M) scanf("%d %d %d", &U[i], &V[i], &W[i]);
	ll C, D;
	cin >> C >> D;
	
	vector<int> ord(M);
	iota(ALL(ord), 0);
	sort(ALL(ord), [&](int x, int y) { return W[x] < W[y]; });
	
	UnionFind uf(N);
	
	auto solve = [&](ll d) {
		ll mn = longINF;
		// 連結成分数を d として C 優先
		// d - 1 本辺を張る必要がある
		if (d - 1 <= A) chmin(mn, (d - 1) * C);
		else {
			// まず A 本つなぐ
			ll cur = C * A;
			ll res = d - A; // 連結成分の個数
			// res 本を B でつなぐ
			if (res == 1) chmin(mn, cur);
			else if (res <= B) chmin(mn, cur + res * D);
		}
		
		// B 優先
		if (d <= B) chmin(mn, d * D);
		else {
			// B 本つなぐ
			ll cur = D * B;
			ll res = d - B + 1;
			if (res - 1 <= A) chmin(mn, cur + (res - 1) * C);
		}
		return mn;
	};
	
	ll edgesum = 0, ans = solve(N);
	ll dcnt = N; // 現在の連結成分数
	
	REP(i, M) {
		int idx = ord[i];
		// 道 idx をつなげる
		if (uf.issame(U[idx], V[idx])) continue;
		uf.unite(U[idx], V[idx]);
		edgesum += W[idx];
		--dcnt;
		ll cur = solve(dcnt);
		if (cur != longINF) chmin(ans, edgesum + cur);
	}
	
	if (ans == longINF) ans = -1;
	cout << ans << endl;
	
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 6984
final_rank: 6