3.41
题意:
给N个点求这N个点全联通的最短距离
(将点转化为实际的数1—2—3—N的之间的距离最短的,求出点点之间的距离,然后根据Kruskall算法求即可)
(主要在于点的转化)
for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { s[k].x=i;///转化为1——2,1——3···1——n、2——3··2——n·········n-n s[k].y=j;/// s[k++].d=sqrt(fabs((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));///距离 } }
代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> using namespace std; const int maxx=105;///N>0&&N<=100; int par[maxx];///存放结点 int n; int k;///存放边的个数(两两之间) struct point { int x;///x为转化后的起点 int y;///y转化后的终点 double d; ///存放x-y的距离 } s[5005]; int cmp(point a,point b) { return a.d<b.d;///按照距离排序(从小到大) } ///初始化 void init() { for(int i=1; i<=n; i++) par[i]=i; } ///寻找根节点(路径压缩) int find(int x) { if(par[x]==x) return x; else return par[x]=find(par[x]); } ///合并 void unite(int x,int y) { x=find(x); y=find(y); if(x!=y) { par[x]=y; } else return ; } ///Kruskall核心算法 void Kruskall() { int a,b; double ll; double sum=0; for(int i=1; i<=k; i++) { a=s[i].x; b=s[i].y; ll=s[i].d; if(find(a)!=find(b)) { sum+=ll; unite(a,b); } } printf("%.2lf\n",sum); } int main() { while(~scanf("%d",&n)) { double x[maxx],y[maxx]; for(int i=1; i<=n; i++) { scanf("%lf%lf",&x[i],&y[i]); } k=1; for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { s[k].x=i;///转化为1——2,1——3···1——n、2——3··2——n·········n-n s[k].y=j;/// s[k++].d=sqrt(fabs((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));///距离 } } sort(s+1,s+k+1,cmp); init(); Kruskall(); } return 0; }