码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4463 Outlets 【最小生成树】

时间:2018-10-07 20:53:59      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:scan   out   cst   print   必须   name   code   int   size   

<题目链接>

题目大意:

给你一些点的坐标,要求你将这些点全部连起来,但是必须要包含某一条特殊的边,问你连起这些点的总最短距离是多少。

解题分析:

因为一定要包含那条边,我们就记录下那条边的边权,然后将那条边边权置为0,再跑一遍最小生成树即可。

#include <cstdio>
#include <cmath> 
#include <cstring>
#include <algorithm>
using namespace std;

int n,s,e,cnt;
struct NODE{
    int x,y;
}node[55];
int father[55];
struct EDGE{
    int x,y;
    double val;
}edge[55*55];

bool cmp(EDGE a,EDGE b){
    return a.val<b.val;
}
double dis(NODE a,NODE b){
    return (double)sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y)*1.0);
}
int find(int x){
    if(father[x]==x)return x;
    father[x]=find(father[x]);
    return father[x];
}
double Kruscal(){
    double sum=0;
    int num=0;
    for(int i=1;i<=n;i++)father[i]=i;
    sort(edge+1,edge+1+cnt,cmp);
    for(int i=1;i<=cnt;i++){
        int f1=find(edge[i].x),f2=find(edge[i].y);
        if(f1!=f2){
            father[f2]=f1;
            sum+=edge[i].val;
            num++;
        }
        if(num==n-1)break;
    }
    return sum;
}
int main(){
    while(scanf("%d",&n)!=EOF,n){
        scanf("%d%d",&s,&e);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&node[i].x,&node[i].y);
        }
        double ans=0;
        cnt=0;
        for(int i=1;i<n;i++){
            for(int j=i+1;j<=n;j++){
                edge[++cnt].x=i,edge[cnt].y=j,edge[cnt].val=dis(node[i],node[j]);
                if(i==s&&j==e||i==e&&j==s){
                    ans+=edge[cnt].val;    //记录下这条边的边权。然后将这条边边权置为0
                    edge[cnt].val=0;
                }
            }
        }
        ans+=Kruscal(); //跑一遍最小生成树
        printf("%.2lf\n",ans);
    }
    return 0;
}

 

2018-10-07

HDU 4463 Outlets 【最小生成树】

标签:scan   out   cst   print   必须   name   code   int   size   

原文地址:https://www.cnblogs.com/00isok/p/9751325.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!