<题目链接>
题目大意:
给你一些点的坐标,要求你将这些点全部连起来,但是必须要包含某一条特殊的边,问你连起这些点的总最短距离是多少。
解题分析:
因为一定要包含那条边,我们就记录下那条边的边权,然后将那条边边权置为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
原文地址:https://www.cnblogs.com/00isok/p/9751325.html
时间: 2024-11-06 18:43:40