最小生成树的一种求法,关键还是判断两个点是否在一个回路上即并查集的运用
#include <iostream> #include<cstdio> #include<algorithm> #include<math.h> using namespace std; int num[210]; int pre[210]; double length; struct edge { int x, y; double w; }e[9999]; void makeSet(int i) { pre[i]=i; num[i]=0; } int findSet(int i) { if(i!=pre[i]) pre[i] = findSet(pre[i]); return pre[i]; } void unionSet(int x, int y, double w) { x = findSet(x); y = findSet(y); if(x==y) return ; length+=w; if(num[x]>num[y]) { pre[y]=x; } else { pre[x] = y; if(num[x]==num[y]) num[y]++; } } bool cmp(const edge &m,const edge &n) { return m.w<n.w; } struct Point { double x,y; }point[105]; int main() { int N,T; cin >>T; while(T--) { cin>>N; for(int i=1;i<=N;i++) cin>>point[i].x>>point[i].y; double t; int c=0; for(int i=1;i<=N;i++) { for(int j=i;j<=N;j++) { t= sqrt((point[i].x-point[j].x)*(point[i].x-point[j].x)+(point[i].y-point[j].y)*(point[i].y-point[j].y)); if(t<10||t>1000) continue; else { e[c].w=t; e[c].x=i; e[c++].y=j; } } } for(int i=0;i<=N;i++) makeSet(i); sort(e,e+c,cmp); length= 0; for(int i=0;i<c;i++) { int x=findSet(e[i].x); int y=findSet(e[i].y); if(x!=y) unionSet(x, y, e[i].w); } if(length>0) { length*= 100; printf("%.1lf\n",length); } else printf("oh!\n"); } }