forwhat00  
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <climits>
#include <algorithm>
using namespace std;
int n;
typedef struct{//边单元
    int from ;
    int to;
    double w;//长度
}node;
typedef struct{ double x , y;}coordinate;//点单元
vector<coordinate>datas;//所有的点
vector<node>edge;//所有的边
int head[120];
double lowc[120];
int vis[120];
void init(){
    datas.clear();
    edge.clear();
    for(int i = 0; i < 120; i ++){
        vis[i] = 0;
        lowc[i] = INT_MAX;
        head[i] = -1;
    }
}
bool cmp(node a , node b){//比较两边
    if(a.from == b.from && a.to == b.to) return a.w < b.w ;
    if(a.from == b.from) return a.to < b.to ;
    return a.from < b.from ;
}
double dist(coordinate a , coordinate b){
    double x = a.x - b.x ;
    double y = a.y - b.y ;
    return sqrt(x*x + y*y);
}
void input(){
    coordinate temp;
    for(int i = 0; i < n; i ++){
        scanf("%lf%lf",&temp.x , &temp.y);
        datas.push_back(temp);
    }
    node temp1;
    for(int i = 0; i < n; i ++)
    for(int j = i + 1; j < n; j ++){
        temp1.from = i;
        temp1.to = j;
        temp1.w = dist(datas[i] , datas[j]);
        edge.push_back(temp1);
        temp1.from = j;
        temp1.to = i;//添加所有可能的边
        edge.push_back(temp1);
    }
    sort(edge.begin() , edge.end() , cmp);//排序
    //以 from - to - 长度 依次比较
    head[0] = 0;
    for(int i = 1; i < (int)edge.size(); i ++){
        if(edge[i].from != edge[i-1].from){
            head[edge[i].from] = i;
        }
    }//记录以某一点为from的边在edge里第一次出现的地方。
}
 
double prim(){
    double res = 0;
    for(int i = head[0]; edge[i].from == 0 && i < n; i ++){
        lowc[edge[i].to] = edge[i].w ;
    }//lowc表示以一点到i点最短边长度
    vis[0] = 1;//0点已放入lowc
    int u ;
    double minc ;
    for(int i = 1; i < n; i ++){
        minc = INT_MAX;
        for(int j  = 0; j < n; j ++){
            if(!vis[j] && lowc[j] < minc ){
                minc = lowc[j];//记录lowc里从某点出发最小边长度
                u = j;//记录另一点的序号
            }
        }
        if(minc == INT_MAX) return -1;
        res += minc ;
        vis[u] = 1;
        for(int j = head[u]; edge[j].from == u && j < (int)edge.size(); j ++){
            //以u为开头的所有边
            if(!vis[edge[j].to] && lowc[edge[j].to] > edge[j].w){
                //如果出现比之前记录的lowc更短的
                lowc[edge[j].to] = edge[j].w;
            }
        }
 
    }
    return res;
}
int main(){
    while(scanf("%d",&n)!=EOF){
        init();
        input();
        printf("%.2lf\n",prim());
    }
    return 0;
}

https://vjudge.net/contest/384914#problem/B

posted on 2020-07-28 17:42  forwhat00  阅读(95)  评论(0编辑  收藏  举报