题意:
现在决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
题解:
裸最小生成树板子
求出两个小岛之间的距离,ans更新的时候需要判断两个小岛之间的距离是否 在【10,1000】之间
最后看图是否联通即 sum 是否等于 n-1 如果不相等则输出 oh!
代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn = 10005; int f[maxn]; int x[maxn],y[maxn]; int n,cnt,m; struct node { int u,v; double w; bool operator < (const node &a)const { return w<a.w; } } edge[maxn]; int Find(int x) { return x==f[x]?x:f[x]=Find(f[x]); } void add(int u,int v,double w) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt++].w=w; } void kruskal() { double ans=0.0; int sum=0; for(int i=0; i<=n; i++)f[i]=i; sort(edge,edge+cnt); for(int i=0; i<cnt; i++) { int x=edge[i].u; int y=edge[i].v; int fx=Find(x); int fy=Find(y); if(fx!=fy && edge[i].w>=10 && edge[i].w<=1000) { f[fx]=fy; sum++; ans+=edge[i].w; } if(sum==n-1)break; } if(sum==n-1)printf("%.1f\n",ans*100); else printf ("oh!\n"); } double get_dis(int i,int j) { double dis=sqrt((x[i]-x[j])*(x[i]-x[j])*1.0+(y[i]-y[j])*(y[i]-y[j])*1.0); return dis; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); cnt=0; for(int i=1; i<=n; i++)scanf("%d%d",&x[i],&y[i]); for(int i=1; i<=n; i++)for(int j=i+1; j<=n; j++) { double dis=get_dis(i,j); add(i,j,dis); } kruskal(); } return 0; }