最小生成树
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define maxn 800
#define maxm 1000
struct Point
{
int x, y;
}point[maxn];
struct Edge
{
int a, b;
}edge[maxn * maxn];
int n, m;
int father[maxn];
int dist(Point a, Point b)
{
Point p;
p.x = a.x - b.x;
p.y = a.y - b.y;
return p.x * p.x + p.y * p.y;
}
bool operator < (const Edge &a, const Edge &b)
{
return dist(point[a.a], point[a.b]) < dist(point[b.a], point[b.b]);
}
int getanc(int a)
{
if (a == father[a])
return a;
return father[a] = getanc(father[a]);
}
void merge(int a, int b)
{
father[getanc(a)] = getanc(b);
}
void input()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d%d", &point[i].x, &point[i].y);
for (int i = 0; i < n; i++)
father[i] = i;
scanf("%d", &m);
for (int i = 0; i < m; i++)
{
int a, b;
scanf("%d%d", &a, &b);
a--;
b--;
merge(a, b);
}
m = 0;
for (int i = 0; i < n - 1; i++)
for (int j = i + 1; j < n; j++)
{
edge[m].a = i;
edge[m].b = j;
m++;
}
}
void work()
{
for (int i = 0; i < m; i++)
if (getanc(edge[i].a) != getanc(edge[i].b))
{
int a = edge[i].a;
int b = edge[i].b;
merge(a, b);
printf("%d %d\n", a + 1, b + 1);
}
}
int main()
{
//freopen("t.txt", "r", stdin);
input();
sort(edge, edge + m);
work();
return 0;
}