题解:
先计算一下任意两点之间的距离,再套用最小生成树模板就行了。
附代码:
#include <set> #include <map> #include <cmath> #include <stack> #include <queue> #include <vector> #include <string> #include <cstdio> #include <cstring> #include <sstream> #include <iomanip> #include <iostream> #include <algorithm> #define clr(str,x) memset(str,x,sizeof(str)) #define FRER() freopen("in.txt","r",stdin); #define FREW() freopen("out.txt","w",stdout); #define MAX_INF 0x7fffffff #define INF 0x3f3f3f3f #define maxn 105 typedef long long int ll; using namespace std; int T,n,m; int pre[maxn]; struct node { int x,y; } nodes[maxn]; struct edge { int u,v; double cost; } edges[maxn*maxn]; bool cmp(edge a,edge b) { return a.cost<b.cost; } int Find(int root) { if(root==pre[root]) return root; return Find(pre[root]); } void Union(int x,int y) { int r1=Find(x),r2=Find(y); if(r1!=r2) pre[r1]=r2; } void Kruskal() { int num=0; double ans=0; for(int i=0; i<m; i++) { int p1=edges[i].u,p2=edges[i].v; int r1=Find(p1),r2=Find(p2); if(r1!=r2) { ans+=edges[i].cost; Union(p1,p2); num++; } if(num>=n-1) break; } if(num<n-1) printf("oh!\n"); else printf("%.1lf\n",ans*100.0); } void init() { memset(nodes,0,sizeof(nodes)); memset(edges,0,sizeof(edges)); m=0; for(int i=0; i<=n; i++) pre[i]=i; } int main() { //FRER() //FREW() scanf("%d",&T); while(T--) { scanf("%d",&n); init(); for(int i=0; i<n; i++) { scanf("%d%d",&nodes[i].x,&nodes[i].y); } for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { double p; p=sqrt(((nodes[i].x-nodes[j].x)*(nodes[i].x-nodes[j].x))+((nodes[i].y-nodes[j].y)*(nodes[i].y-nodes[j].y))); if(p<10.0||p>1000.0) continue; edges[m].u=i,edges[m].v=j; edges[m++].cost=p; } } sort(edges,edges+m,cmp); Kruskal(); } return 0; }