bzoj1626[Usaco2007 Dec]Building Roads 修建道路*

bzoj1626[Usaco2007 Dec]Building Roads 修建道路

题意:

坐标系上n个点,其中一些点连了边,问使点连通还要连边的最小总长度。n≤1000。

题解:

用并查集维护连通块,先将连好边的点合并,然后再按长度从小到大连边。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define maxn 1100
 6 #define inc(i,j,k) for(int i=j;i<=k;i++)
 7 #define ll long long
 8 using namespace std;
 9 
10 inline int read(){
11     char ch=getchar(); int f=1,x=0;
12     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
13     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
14     return f*x;
15 }
16 int n,m,fa[maxn],cnt; ll x[maxn],y[maxn];
17 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
18 struct e{int f,t; ll len;}; e es[maxn*maxn]; int ess;
19 bool cmp(e a,e b){return a.len<b.len;}
20 inline bool merge(int _x,int _y){int x=find(_x),y=find(_y); if(x==y)return 0; fa[x]=y; return 1;}
21 int main(){
22     n=read(); m=read(); inc(i,1,n)x[i]=read(),y[i]=read(),fa[i]=i;
23     inc(i,1,n)inc(j,i+1,n)es[++ess]=(e){i,j,(x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i])};
24     sort(es+1,es+ess+1,cmp);
25     inc(i,1,m){int a=read(),b=read(); if(merge(a,b))cnt++;} double ans=0;
26     inc(i,1,ess){if(merge(es[i].f,es[i].t))ans+=sqrt(es[i].len),cnt++; if(cnt==n-1)break;}
27     printf("%.2lf",ans); return 0;
28 }

 

20160727

posted @ 2016-07-27 23:25  YuanZiming  阅读(197)  评论(0编辑  收藏  举报