P2872 [USACO07DEC]Building Roads S

凡是存在边的两个点,设它们的边权为0,其他不存在边的两点之间的距离按照欧拉距离来算,这样只要求一遍最小生成树就可以得到加边的最小值。
复杂度:(O(n^2))

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>

using namespace std;

const int N = 1010;
const double INF = 0x7f7f7f7f7f7f7f7f;

struct Node{
    double x, y;
}node[N];

int st[N];
bool g[N][N];
double dist[N];
int n, m;

double calc(int a, int b){
    double dx = node[a].x - node[b].x;
    double dy = node[a].y - node[b].y;
    return (double) sqrt(dx * dx + dy * dy);
}

double prim(){
    memset(dist, 0x7f, sizeof dist);
    
    double res = 0;
    
    for(int i = 0; i < n; i ++){
        int k = -1;
        
        for(int j = 0; j < n; j ++)
            if(st[j] == 0 && (k == -1 || dist[k] > dist[j]))
                k = j;
        
        st[k] = 1;
        
        for(int j = 0; j < n; j ++)
            if(st[j] == 0)
                dist[j] = min(dist[j], g[k][j] ? (double) 0 : calc(k, j));
                
        if(i) res += dist[k];
    }
    
    return res;
}

int main(){
    cin >> n >> m;
    
    for(int i = 0; i < n; i ++){
        double a, b;
        cin >> a >> b;
        
        node[i] = {a, b};
    }
    
    while(m --){
        int a, b;
        cin >> a >> b;
        
        a --, b --;
        
        g[a][b] = g[b][a] = 1;
    }
    
    printf("%.2lf", prim());
    
    return 0;
}
原文地址:https://www.cnblogs.com/tomori/p/13810862.html