题目链接:https://cn.vjudge.net/problem/POJ-1751
题目:给出n个点的坐标,然后,有m条路已经修好,问把所有点都联系起来,最小的花费是多少。
分析:最小生成树。。。先把已经修好的连起来,再用最小生成树求就可以了。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
int n,m,cnt,pre[800],l[800],r[800];
double x[800],y[800];
struct node{
int l,r;
double d;
}mp[1000010];
void init()
{
cnt = 0;
for(int i=1;i<=n;i++)
pre[i] = i;
}
bool cmp(const node x,const node y)
{
return x.d < y.d;
}
int find(int x)
{
int r = x;
while(r != pre[r])
r = pre[r];
int tmp,a = x;
while(a != r)
{
tmp = pre[a];
pre[a] = r;
a = tmp;
}
return r;
}
void unionn(int x,int y)
{
int rx = find(x);
int ry = find(y);
if(rx != ry)
pre[ry] = rx;
}
int main()
{
scanf("%d",&n);
init();
for(int i=1;i<=n;i++)
scanf("%lf%lf",&x[i],&y[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
unionn(a,b);
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
double dis = sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) );
mp[cnt].l = i;
mp[cnt].r = j;
mp[cnt].d = dis;
cnt++;
}
}
sort(mp,mp+cnt,cmp);
int num = 0;
for(int i=0;i<cnt;i++)
{
int rx=find(mp[i].l);
int ry=find(mp[i].r);
if(rx != ry)
{
pre[ry] = rx;
l[num] = mp[i].l;
r[num] = mp[i].r;
num++;
}
}
if(num == 0)
printf("\n");
else
{
for(int i=0;i<num;i++)
printf("%d %d\n",l[i],r[i]);
}
return 0;
}