Problem:
JOI 公園 (JOI Park)

20XX 年に IOI 国で行われるオリンピックに備え，IOI 国にある JOI 公園を整備することになった．JOI公園には N 個の広場があり，広場には 1 から N の番号がついている．広場を繋ぐ M 本の道があり，道には 1 から M の番号がついている．道 i (1 ≤ i ≤ M) は広場 Ai と広場 Bi を双方向に繋いでおり，長さは Di である．どの広場からどの広場へもいくつかの道を辿って行くことができる．

整備計画では，まず，0 以上の整数 X を選び，広場 1 からの距離が X 以下であるような広場 (広場 1 を含む) どうしをすべて相互に地下道で結ぶ．ただし，広場 i と広場 j の距離とは，広場 i から広場 j に行くときに通る道の長さの和の最小値である．整備計画では地下道の整備コストに関する整数 C が定まっている．地下道の整備にかかるコストは C × X である．

次に，地下道で結ばれた広場どうしを結ぶ道をすべて撤去する．道の撤去にコストはかからない．最後に，撤去されずに残った道をすべて補修する．長さ d の道を補修するためにかかるコストは d である．整備計画実施前の JOI 公園には地下道はない．JOI 公園の整備にかかるコストの和の最小値を求めよ．

課題

JOI 公園の広場の情報と，地下道の整備コストに関する整数が与えられたとき，JOI 公園の整備にかかる
コストの和の最小値を求めるプログラムを作成せよ．

入力

標準入力から以下のデータを読み込め．

1 行目には，整数 N, M,C が空白を区切りとして書かれている．これは，広場が N 個，道が M 本あり，地下道の整備コストに関する整数が C であることを表す．

続く M 行のうちの i 行目 (1 ≤ i ≤ M) には，整数 Ai, Bi, Di が空白を区切りとして書かれている．これは，道 i が広場 Ai と広場 Bi を繋ぎ，長さが Di であることを表す．

出力

標準出力に，JOI 公園の整備にかかるコストの和の最小値を表す整数を 1 行で出力せよ．

制限

すべての入力データは以下の条件を満たす．

2 ≤ N ≤ 100 000．

1 ≤ M ≤ 200 000．

1 ≤ C ≤ 100 000．

1 ≤ Ai ≤ N (1 ≤ i ≤ M)．

1 ≤ Bi ≤ N (1 ≤ i ≤ M)．

Ai ≠ Bi (1 ≤ i ≤ M)．

(Ai, Bi) ≠ (Aj, Bj) および (Ai, Bi) ≠ (Bj, Aj) (1 ≤ i < j ≤ M)．

1 ≤ Di ≤ 100 000 (1 ≤ i ≤ M)．

与えられる入力データにおいては，どの広場からどの広場へもいくつかの道を辿ることにより行けることが保証されている．

入出力例

入力例 1

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

出力例 1

14

この入力例では，X = 3 として，広場 1 からの距離が 3 以下であるような広場 (広場 1, 広場 2, 広場 3) どうしをすべて相互に地下道で結んだとき，整備にかかるコストの和は 2 × 3 + 3 + 5 = 14 となる．これが最小値である．

入力例 2

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

出力例 2

15

この入力例では，X = 0 のとき整備にかかるコストの和が最小になる．

入力例 3

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

出力例 3

10

この入力例では，X = 5 としてすべての広場を相互に地下道で結んだとき，整備にかかるコストの和が最小になる．

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in C++ (judge verdict: Accepted)

#include <bits/stdc++.h>

#define MAX_N (100100)
#define MAX_M (200100)

using namespace std;

typedef long long Int;
typedef pair<Int, int> Stat;

const Int INF = 1001001001001001001ll;

int N, M;
Int C;

int head[MAX_N], to[2 * MAX_M], nxt[2 * MAX_M], cost[2 * MAX_M];
Int dist[MAX_N];

void addEdge(int id, int a, int b, int c)
{
    nxt[id] = head[a];
    to[id] = b;
    cost[id] = c;
    head[a] = id;
}

int main()
{
    scanf("%d %d %lld", &N, &M, &C);
    
    memset(head, -1, sizeof(head));
    
    Int sum = 0;
    for (int i = 0; i < M; i++){
        int A, B, D;
        scanf("%d %d %d", &A, &B, &D);
        addEdge(i * 2    , A, B, D);
        addEdge(i * 2 + 1, B, A, D);
        
        sum += D;
    }
    
    fill(dist + 1, dist + N + 1, INF);
    
    priority_queue<Stat, vector<Stat>, greater<Stat> > pq;
    
    for (pq.push(Stat(0, 1)); pq.size();){
        Stat tmp = pq.top(); pq.pop();
        
        Int d = tmp.first;
        int v = tmp.second;
        
        if (dist[v] != INF) continue;
        dist[v] = d;
        for (int e = head[v]; e != -1; e = nxt[e]){
            pq.push(Stat(d + cost[e], to[e]));
        }
    }
    
    pair<Int, int> distPair[MAX_N];
    for (int i = 1; i <= N; i++){
        distPair[i - 1] = make_pair(dist[i], i);
    }
    
    sort(distPair, distPair + N);
    
    Int ans = sum;
    set<int> s;
    for (int i = 0; i < N;){
        int j;
        for (j = i; j < N && distPair[i].first == distPair[j].first; j++){
            s.insert(distPair[j].second);
            int v = distPair[j].second;
            for (int e = head[v]; e != -1; e = nxt[e]){
                if (s.find(to[e]) != s.end()){
                    sum -= cost[e];
                }
            }
        }
        ans = min(ans, sum + distPair[i].first * C);
        i = j;
    }
    
    printf("%lld\n", ans);
    
    return (0);
}