1. 程式人生 > >HDU 4463 Outlets 【最小生成樹】

HDU 4463 Outlets 【最小生成樹】

let .net 鏈接 全部 題目 () 生成樹 father for

<題目鏈接>

題目大意:

給你一些點的坐標,要求你將這些點全部連起來,但是必須要包含某一條特殊的邊,問你連起這些點的總最短距離是多少。

解題分析:

因為一定要包含那條邊,我們就記錄下那條邊的邊權,然後將那條邊邊權置為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 【最小生成樹】