HDU 1162 Eddy's picture(最小生成树-Prim)

Description
给出n个点,用最短的线段将这些点连起来,输出最短长度
Input
多组输入,每组用例第一行为点数n,之后n行每行两个浮点数表示该点横纵坐标,以文件尾结束输入
Output
对于每组用例,输出最短线段长度,结果保留小数点后两位
Sample Input
3
1.0 1.0
2.0 2.0
2.0 4.0
Sample Output
3.41
Solution
最小生成树裸题,套Prim或者Kruskal模版均可
Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 111
double cost[maxn][maxn];//cost[u][v]表示的是边e=(u,v)的权值(不存在的时候设为INF)
double mincost[maxn];//从集合X出发的边到每个顶点的最小权值
bool used[maxn];//顶点i是否包含在集合X中
int V;//顶点数
double prim()
{
    for(int i=0;i<V;i++)//初始化 
    {
        mincost[i]=cost[0][i];
        used[i]=false;
    }
    used[0]=true;//把第一个顶点加进集合X中 
    double res=0.0; 
    for(int i=1;i<V;i++)
    {
        int v=-1;
        double minc=1.0*INF;
        for(int u=0;u<V;u++)//从不属于集合X的顶点中选取从X到其权值最小的顶点 
            if(!used[u]&&mincost[u]<minc)
                v=u,minc=mincost[u];
        if(v==-1)break;
        used[v]=true;//把顶点v加到集合X中
        res+=minc;//把边权加到结果中 
        for(int u=0;u<V;u++)//mincost中始终存的是集合X中元素到每个顶点的最小权值 
            mincost[u]=min(mincost[u],cost[u][v]); 
    }
    return res;
} 
struct node
{
    double x,y;
}p[maxn];
double dis(node a,node b)//两点间距离 
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main()
{
    while(~scanf("%d",&V))
    {
        for(int i=0;i<V;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        for(int i=0;i<V;i++)//注意初始化 
            cost[i][i]=INF;
        for(int i=0;i<V;i++)
            for(int j=i+1;j<V;j++)
                cost[j][i]=cost[i][j]=dis(p[i],p[j]);
        double ans=prim(); 
        printf("%.2lf\n",ans);
    }
    return 0;
}

你可能感兴趣的:(HDU 1162 Eddy's picture(最小生成树-Prim))