Time limit per test: 2.0 seconds

Memory limit: 256 megabytes

Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.

Each of the N (1≤N≤1 000) farms (conveniently numbered 1..N) is represented by a position (Xi,Yi) on the plane (0≤Xi≤1 000 000, 0≤Yi≤1 000 000). Given the preexisting M roads (1≤M≤1 000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.

Input
Line 1: Two space-separated integers: N and M
Lines 2..N+1: Two space-separated integers: Xi and Yi
Lines N+2..N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.
Output
Line 1: Smallest length of additional roads required to connect allfarms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.
Examples
input
4 1
1 1
3 1
2 3
4 3
1 4
output
4.00
Note
INPUT DETAILS:

Four farms at locations (1,1), (3,1), (2,3), and (4,3). Farms 1 and 4 are connected by a road.

OUTPUT DETAILS:

Connect farms 1 and 2 with a road that is 2.00 units long, then connect farms 3 and 4 with a road that is 2.00 units long. This is the best we can do, and gives us a total of 4.00 unit lengths.

题意:已经有M条道路连通,求至少还要修多少米才能使任意两个农庄连通。
分析:最小生成树
可用prim算法和kruskal算法
我用了kruskal算法, 好像本题用prim算法更快

注意:kruskal算法中组成图的边的条数必不小于N*N, 否则RE
代码:

#include <bits/stdc++.h>
using namespace std;

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)
#define dec(i,n,a) for(int i=n;i>=a;i--)///[n,a]
#define pb push_back
#define fi first
#define se second
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const double PI=acos(-1.0);
const double E=2.718281828459045;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const int MOD=258280327;
const int N=1e3+5;
const ll maxn=1e6+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
struct position
{
    double x,y;
} a[N];
struct Node
{
    int u,v;
    double cost;
    Node() {}
    Node(int u,int v,double cost):u(u),v(v),cost(cost) {}
    bool operator < (const Node& m)const
    {
        return cost<m.cost;
    }
} g[maxn];
int par[N];
void init(int n)
{
    rep(i,0,n+1) par[i]=i;
}
int Find(int x)///非递归更快  卡时间 用此种形式更好
{
    int r=x;
    while(r!=par[r]) r=par[r];
    int tmp=x;
    while(tmp!=r)
    {
        int fa=par[tmp];
        par[tmp]=r;
        tmp=fa;
    }
    return r;
}
/*
int Find(int x)
{
    return par[x]==x?x:Find(par[x]);
}*/
bool unite(int x,int y)
{
    x=Find(x),y=Find(y);
    if(x!=y)
    {
        par[x]=y;
        return true;
    }
    return false;
}
double cal_dis(position a,position b)
{
    double t1=a.x-b.x,t2=a.y-b.y;
    return sqrt(t1*t1+t2*t2);
}
void solve(int n)
{
    sort(g,g+n);
    double ans=0;
    rep(i,0,n)
    {
        Node tmp=g[i];
        if(unite(tmp.u,tmp.v))
            ans+=tmp.cost;
    }
    printf("%.2lf\n",ans);
}
int main()
{
    //fre;
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        init(n);
        rep(i,0,n) scanf("%lf%lf",&a[i].x,&a[i].y);
        int cnt=0;
        rep(i,0,n-1)
        {
            rep(j,i+1,n)
            g[cnt++]=Node(i+1,j+1,cal_dis(a[i],a[j]));
        }
        while(m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            unite(u,v);
        }
        //printf("cnt=%d\n",cnt);
        solve(cnt);
    }
    return 0;
}