結果

問題 No.168 ものさし
ユーザー @abcde@abcde
提出日時 2019-06-26 01:32:35
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 29 ms / 2,000 ms
コード長 2,300 bytes
コンパイル時間 1,863 ms
コンパイル使用メモリ 176,728 KB
実行使用メモリ 12,752 KB
最終ジャッジ日時 2024-06-23 15:20:11
合計ジャッジ時間 2,923 ms
ジャッジサーバーID
(参考情報)
judge4 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 9 ms
6,812 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 AC 2 ms
6,944 KB
testcase_03 AC 2 ms
6,940 KB
testcase_04 AC 2 ms
6,940 KB
testcase_05 AC 2 ms
6,940 KB
testcase_06 AC 2 ms
6,944 KB
testcase_07 AC 2 ms
6,940 KB
testcase_08 AC 2 ms
6,940 KB
testcase_09 AC 2 ms
6,940 KB
testcase_10 AC 2 ms
6,944 KB
testcase_11 AC 8 ms
6,940 KB
testcase_12 AC 22 ms
12,048 KB
testcase_13 AC 29 ms
12,472 KB
testcase_14 AC 28 ms
12,544 KB
testcase_15 AC 2 ms
6,940 KB
testcase_16 AC 2 ms
6,944 KB
testcase_17 AC 3 ms
6,940 KB
testcase_18 AC 3 ms
6,944 KB
testcase_19 AC 28 ms
12,204 KB
testcase_20 AC 29 ms
12,752 KB
testcase_21 AC 29 ms
12,192 KB
testcase_22 AC 28 ms
12,724 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// 以下のライブラリを使ってみる.
// 素集合データ構造(Union-Find)
// https://ei1333.github.io/luzhiled/snippets/structure/union-find.html
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

struct UnionFind{

    vector<LL> data;
    UnionFind(LL sz){ data.assign(sz, -1); }
    
    // 頂点 x, y の 結合.
    bool unite(LL x, LL y){
        x = find(x), y = find(y);
        if(x == y)            return false;
        if(data[x] > data[y]) swap(x, y);
        data[x] += data[y];
        data[y] = x;
        return true;
    }
    
    // 頂点 k を 探索.
    LL find(LL k){
        if(data[k] < 0) return k;
        return data[k] = find(data[k]);
    }
    
    // 頂点 k を含む集合 の 大きさ.
    LL size(LL k){ return (-data[find(k)]); }
};

// 辺
// f: 始点
// t: 終点
// c: 距離.
struct edge{
    int f, t;
    LL c;
    bool operator < (const edge& rhs) const{
        if (c > rhs.c) return true;
        else           return false;
    }
};

int main(){

    // 1. 入力情報取得.
    int N;
    scanf("%d", &N);
    LL x[N], y[N];
    for(int i = 0; i < N; i++) scanf("%llu %llu", x + i, y + i);
    
    // 2. Union-Find木.
    priority_queue<edge> pq;
    UnionFind uf(N);
    
    // 3. 各2点間の距離を計算.
    // 下記, 解説サイト参照.
    // https://kenkoooo.hatenablog.com/entry/2015/03/20/011546
    for(int i = 0; i < N; i++){
        for(int j = 0; j < i; j++){
            LL dx = x[i] - x[j], dy = y[i] - y[j];
            LL d2 = dx * dx + dy * dy;
            LL d = sqrt(d2);
            while(d2 > d * d) d++;
            d = (d + 9LL) / 10LL * 10LL;
            edge e;
            e.f = i, e.t = j, e.c = d;
            pq.push(e);
            // cout << "i=" << i << " j=" << j << " d=" << d << " d2=" << d2 << endl;
        }
    }
    
    // 4. A君が買う必要のある最も短いものさしは?
    LL ans = 0LL;
    while(uf.find(0) != uf.find(N - 1)){
        edge e = pq.top();
        pq.pop();
        // cout << "e.f=" << e.f << " e.t=" << e.t << " e.c=" << e.c << endl;
        if(uf.find(e.f) != uf.find(e.t)){
            uf.unite(e.f, e.t);
            ans = max(ans, e.c);
        }
    }
    
    // 5. 後処理.
    printf("%llu\n", ans);
    return 0;

}
0