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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章