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