最小生成树的变体,没有给边的权重,而是给了节点信息。对于每一个节点对,可以计算出边的权重,然后再用kruskal算法解决。

#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
using namespace std;

//习题11.4
const int maxn=1010;
int father[maxn];
int height[maxn];
struct edge{
    int node1;
    int node2;
    float dist;
};

struct node{
    float x;
    float y;
};

node nodelist[maxn];
edge graph[maxn*maxn];

//初始化
void initial(){
    for(int i=0;i<=maxn;i++){
        father[i]=-1;
        height[i]=0;
    }
}
//Find
int Find(int x){
    if (father[x]==-1)return x;
    return Find(father[x]);
}
//union
void Union(int x,int y){
    int fx=Find(x);
    int fy=Find(y);
    if (fx==fy)return;
    if(height[fx]>height[fy]){
        father[fy]=fx;
    }
    else if(height[fx]<height[fy]){
        father[fx]=fy;
    }
    else{
        father[fx]=fy;
        height[fy]++;
    }
}


int compare(edge x,edge y){
    return x.dist<y.dist;
}

//核心算法!!
float kruskal(int edgenumber){
    float sum=0;
    for(int i=0;i<edgenumber;i++){
        edge e=graph[i];
        if (Find(e.node1)!=Find(e.node2)){
            Union(e.node1,e.node2);
            sum+=e.dist;
        }
    }
    return sum;
}


int main(){
    int n;
    while(cin>>n){
        initial();
        for(int i=0;i<n;i++){
            cin>>nodelist[i].x>>nodelist[i].y;
        }
        int ed_id=0;
        for(int i=0;i<n-1;i++){
            for(int j=i+1;j<n;j++){
                node n1=nodelist[i];
                node n2=nodelist[j];
                float dist=sqrt((n1.x-n2.x)*(n1.x-n2.x)+(n1.y-n2.y)*(n1.y-n2.y));
                graph[ed_id].dist=dist;
                graph[ed_id].node1=i;
                graph[ed_id].node2=j;
                ed_id++;
            }
        }
        sort(graph,graph+ed_id,compare);
        float sum=kruskal(ed_id);
        printf("%.2f\n",sum);
    }
    return 0;
}