HOJ2064 - Journey to Tibet - 並查集+暴力

Journey to Tibet

題目鏈接

分類dsu brute force

1.題意概述

  • ​ 給出你n(1n1000) 個寺廟的座標,相鄰兩個寺廟,你最多隻能走30km 現在問你總哪個起點出發,能夠走儘可能多的寺廟,相同則輸出輸入編號的最小值。

2.解題思路

  • 這題本質是求最大的連通塊,連通問題,我們都可以考慮用並查集維護,父親就是集合裏面id最小的,因爲n很小,我們O(n2) 地暴力維護任意兩個寺廟的最短路徑,然後再掃一遍集合求出最大值即可。

3.AC代碼

vector<int> g[N];
struct node {
    int x, y, c;
} p[N];
int pa[N];
void init() {
    rep(i, 0, N) {
        g[i].clear();
        pa[i] = i;
    }
}
int find(int x) {
    if (x == pa[x]) return x;
    return pa[x] = find(pa[x]);
}
void merge(int a, int b) {
    int a1 = find(a);
    int b1 = find(b);
    if (a1 == b1) return;
    if (a1 < b1) pa[b1] = a1;
    else pa[a1] = b1;
}
int getdis(int a, int b) {
    return (p[a].x - p[b].x) * (p[a].x - p[b].x) + (p[a].y - p[b].y) * (p[a].y - p[b].y);
}
inline void solve() {
    int n;
    while (~scanf("%d", &n) && n) {
        init();
        rep(i, 1, n + 1) scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].c);
        rep(i, 1, n) {
            rep(j, i + 1, n + 1) {
                int dis = getdis(i, j);
                if (dis <= 900) merge(i, j);
            }
        }
        rep(i, 1, n + 1)  {
            int fa = find(i);
            g[fa].pb(i);
        }
        int P = 1, ans = 0;
        rep(i, 1, n + 1) {
            int sum = 0;
            int u = i;
            rep(j, 0, SZ(g[i])) {
                u = min(u, g[i][j]);
                sum += p[g[i][j]].c;
            }
            if (sum > ans) {
                ans = sum;
                P = u;
            } else if (ans == sum && u < P) P = u;
        }
        printf("%d %d\n", P, ans);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章