P2872 [USACO07DEC] Building Roads S

发布于:2025-08-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

P2872 [USACO07DEC] Building Roads S

题目描述

给定 nnn 个点的坐标,第 iii 个点的坐标为 (xi,yi)(x_i,y_i)(xi,yi),这 nnn 个点编号为 111nnn。给定 mmm 条边,第 iii 条边连接第 uiu_iui 个点和第 viv_ivi 个点。现在要求你添加一些边,并且能使得任意一点都可以连通其他所有点。求添加的边的总长度的最小值。

输入格式

第一行两个整数 n,mn,mn,m 代表点数与边数。
接下来 nnn 行每行两个整数 xi,yix_i,y_ixi,yi 代表第 iii 个点的坐标。
接下来 mmm 行每行两个整数 ui,viu_i,v_iui,vi 代表第 iii 条边连接第 uiu_iui 个点和第 viv_ivi 个点。

输出格式

一行一个实数代表添加的边的最小长度,要求保留两位小数,为了避免误差,请用 646464 位实型变量进行计算。

输入输出样例 #1

输入 #1

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

输出 #1

4.00

说明/提示

数据规模与约定

对于 100%100\%100% 的整数,1≤n,m≤10001 \le n,m \le 10001n,m10001≤xi,yi≤1061 \le x_i,y_i \le 10^61xi,yi1061≤ui,vi≤n1 \le u_i,v_i \le n1ui,vin

说明

Translated by 一只书虫仔。

其实还是求MST,只不过边变成了未联通的边。将已给出的边以权值0加入边数组中,跑一下最短路即可。

#include<bits/stdc++.h>
#define ll long long int
using namespace std;

int find_(vector<int> &p, int x){
    if(p[x] == x) return x;
    else {
        p[x] = find_(p, p[x]);
        return p[x];
    }
}
int main(){
    int n, m;
    cin>>n>>m;
    vector<pair<ll, ll>> p(n+1);
    for(int i = 1;i<=n;i++){
        cin>>p[i].first>>p[i].second;
    }
    vector<tuple<long double, int, int>> e;
    for(int i = 0;i<m;i++){
        int u, v;
        cin>>u>>v;
        e.emplace_back(0.0, u, v);
    }
    for(int i = 1;i<n;i++){
        for(int j = i+1;j<=n;j++){
            e.emplace_back(sqrt((p[i].first-p[j].first)*(p[i].first-p[j].first) + (p[i].second-p[j].second)*(p[i].second-p[j].second)), i, j);
        }
    }
    sort(e.begin(), e.end());
    vector<int> pa(n+1);
    for(int i = 1;i<=n;i++){
        pa[i] = i;
    }
    double sum = 0;
    int cnt = 0;
    for(auto i : e){
        auto [w, u, v] = i;
        int r1 = find_(pa, u);
        int r2 = find_(pa, v);
        if(r1 != r2){
            pa[r1] = r2;
            sum+=w;
            cnt++;
        }
        if(cnt==n-1) break;
    }
    printf("%.2lf", sum);
    return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到