HDU 4463 Outlets 【最小生成树】

<题目链接>

题目大意:

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

解题分析:

因为一定要包含那条边,我们就记录下那条边的边权,然后将那条边边权置为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

posted @ 2018-10-07 20:36  悠悠呦~  阅读(163)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end