时间:2016-04-13 23:58:24 星期三
题目编号:[2016-04-13][HDU][1875][畅通工程再续]
题目大意:求边权在指定范围内的最小生成树
分析:kruskal合并的时候判断一下,最后判断一下合并的边数是否为n-1
#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int maxn = 100 + 10;struct Point{ int x,y; Point(int a=0,int b=0):x(a),y(b){}}p[maxn];struct Edge{ int u,v, c; Edge(int a=0,int b=0,int cc=0):u(a),v(b),c(cc){} bool operator < (const Edge & a)const{ return c < a.c; }}e[maxn * maxn];int fa[maxn];int fnd(int x){ return x == fa[x]?x:fa[x] = fnd(fa[x]);}void ini(int n){ for(int i = 0 ; i <= n ; ++i){ fa[i] = i; }}int dis(int a,int b){ return (p[a].x - p[b].x)*(p[a].x - p[b].x ) + (p[a].y - p[b].y) * (p[a].y - p[b].y);}int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); ini(n); for(int i = 0 ; i < n ; ++i){ scanf("%d%d",&p[i].x,&p[i].y); } int cnt = 0; for(int i = 0; i < n ; ++i){ for(int j = 0 ; j < n ; ++j){ e[cnt++] = Edge(i,j,dis(i,j)); } } sort(e,e+cnt); int k = 0;double ans = 0; for(int i = 0 ; i < cnt ; ++i){ int f1 = fnd(e[i].u); int f2 = fnd(e[i].v); if(f1 != f2 && e[i].c >= 100 && e[i].c <= 1000*1000){ fa[f1] = f2; ans += sqrt(double( e[i].c)); ++k; } if(k == n - 1) break; } if(k == n - 1) printf("%.1lf\n",ans * 100); else puts("oh!"); } return 0;}