Problem p03440 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 1000000000000;
const int mod = 1000000007;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
int par[12345678]; // 親
int rnk[12345678]; // 木のランク
// n要素で初期化
void init(int n) {
  for (int i = 0; i <= n; i++) {
    par[i] = i;
    rnk[i] = 0;
  }
}
// 木の根を求める
int find(int x) {
  if (par[x] == x) {
    return x;
  } else {
    return par[x] = find(par[x]);
  }
}
// xとyの属する集合を併合
void unite(int x, int y) {
  x = find(x);
  y = find(y);
  if (x == y) {
    return;
  }
  if (rnk[x] < rnk[y]) {
    par[x] = y;
  } else {
    par[y] = x;
    if (rnk[x] == rnk[y])
      rnk[x]++;
  }
}
// xとyが同じ集合に属するか否か
bool same(int x, int y) { return find(x) == find(y); }
int cost[12345678], kari[12345678];
signed main() {
  int n, m, a, s, t, x = 0, y = 0, ans = 0;
  cin >> n >> m;
  vector<vector<int>> v(123456);
  vector<int> S, cnt;
  init(n);
  for (int h = 0; h < n; h++) {
    cin >> a;
    cost[h] = a;
  }
  for (int h = 0; h < m; h++) {
    cin >> s >> t;
    unite(s, t);
  }
  for (int h = 0; h < n; h++) {
    int z = find(h);
    v[z].push_back(cost[h]);
    if (kari[z] == 0) {
      S.push_back(z);
      kari[z]++;
    }
  }
  for (int h = 0; h < S.size(); h++) {
    sort(v[S[h]].begin(), v[S[h]].end());
  }
  if ((S.size() - 1) * 2 > n) {
    cout << "Impossible" << endl;
    return 0;
  }
  if (n == 1) {
    cout << 0 << endl;
    return 0;
  }
  for (int h = 0; h < S.size(); h++) {
    ans += v[S[h]][0];
    cnt.push_back(v[S[h]][0]);
  }
  sort(cnt.begin(), cnt.end());
  sort(cost, cost + n);
  for (int h = 0; h < (S.size() - 1) * 2 - S.size(); h++) {
    while (cost[x] == cnt[y]) {
      x++;
      y++;
    }
    ans += cost[x];
    x++;
  }
  cout << ans << endl;
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 1000000000000;
const int mod = 1000000007;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
int par[12345678]; // 親
int rnk[12345678]; // 木のランク
// n要素で初期化
void init(int n) {
  for (int i = 0; i <= n; i++) {
    par[i] = i;
    rnk[i] = 0;
  }
}
// 木の根を求める
int find(int x) {
  if (par[x] == x) {
    return x;
  } else {
    return par[x] = find(par[x]);
  }
}
// xとyの属する集合を併合
void unite(int x, int y) {
  x = find(x);
  y = find(y);
  if (x == y) {
    return;
  }
  if (rnk[x] < rnk[y]) {
    par[x] = y;
  } else {
    par[y] = x;
    if (rnk[x] == rnk[y])
      rnk[x]++;
  }
}
// xとyが同じ集合に属するか否か
bool same(int x, int y) { return find(x) == find(y); }
int cost[12345678], kari[12345678];
signed main() {
  int n, m, a, s, t, x = 0, y = 0, ans = 0;
  cin >> n >> m;
  vector<vector<int>> v(123456);
  vector<int> S, cnt;
  init(n);
  for (int h = 0; h < n; h++) {
    cin >> a;
    cost[h] = a;
  }
  for (int h = 0; h < m; h++) {
    cin >> s >> t;
    unite(s, t);
  }
  for (int h = 0; h < n; h++) {
    int z = find(h);
    v[z].push_back(cost[h]);
    if (kari[z] == 0) {
      S.push_back(z);
      kari[z]++;
    }
  }
  for (int h = 0; h < S.size(); h++) {
    sort(v[S[h]].begin(), v[S[h]].end());
  }
  if ((S.size() - 1) * 2 > n) {
    cout << "Impossible" << endl;
    return 0;
  }
  if (S.size() == 1) {
    cout << 0 << endl;
    return 0;
  }
  for (int h = 0; h < S.size(); h++) {
    ans += v[S[h]][0];
    cnt.push_back(v[S[h]][0]);
  }
  sort(cnt.begin(), cnt.end());
  sort(cost, cost + n);
  for (int h = 0; h < (S.size() - 1) * 2 - S.size(); h++) {
    while (cost[x] == cnt[y]) {
      x++;
      y++;
    }
    ans += cost[x];
    x++;
  }
  cout << ans << endl;
  return 0;
}