HDU 4463 Outlets 【最小生成樹】
阿新 • • 發佈:2018-10-07
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 【最小生成樹】