// 最小树形图的朱刘算法
// 临接表实现
// 题目:poj3164
// 时间复杂度,据说是O(VE)
// 2011年9月15日
//
#include <iostream>
#include <cstdio>
#include <cmath>
#include <memory.h>
#define scale 110
#define eps 1e-8
using namespace std;
struct Node {
int to;
double value;
bool flag;
Node * next;
} array[scale*scale];
int amount;
Node * graph[scale]; //邻接表存有向图
struct cost_from {
double cost;
int from, circle_id;
} mini[scale]; //记录最小入边
void dfs(int * flag, int t) {
flag[t] = 1;
Node * p = graph[t];
while (p != NULL) {
if (!flag[p->to]) dfs(flag, p->to);
if (p->to == t) p->flag = false; //去掉自环
p = p->next;
}
}
double zhuliu(int n, int root) {
int i, j, temp;
int flag[scale], id[scale], new_id[scale];
double sum;
bool sign;
Node * p;
memset(flag, 0, sizeof(flag));
dfs(flag, root); //判断能否从跟到达所有节点
for (i = 0; i < n; i++) {
id[i] = i;
if (!flag[i]) return -1;
}
if (true) sum = 0;
while (true) {
for (i = 0; i < n; i++) mini[i].from = -1;
for (i = 0; i < n; i++) {
p = graph[i];
while (p != NULL) {
if (p->flag && p->to != root) {
j = id[p->to];
if (mini[j].from == -1 || mini[j].cost > p->value) {
mini[j].cost = p->value;
mini[j].from = id[i];
}
}
p = p->next;
}
}
sign = false;
memset(flag, -1, sizeof(flag));
memset(new_id, -1, sizeof(new_id));
for (i = 0; i < n; i++) {
if (mini[i].from != -1) {
if (new_id[i] == -1) {
j = i;
do {
flag[j] = i;
j = mini[j].from;
} while (j != -1 && flag[j] == -1);
if (j != -1 && flag[j] == i) { //构成环
sign = true;
temp = j;
do {
new_id[j] = temp; //环中顶点被赋予相同的id
j = mini[j].from;
} while (j != temp);
}
}
sum += mini[i].cost;
}
}
if (!sign) break; //没有构成环就退出
else {
for (i = 0; i < n; i++) {
p = graph[i];
while (p != NULL) {
if (p->flag && p->to != root) {
j = new_id[id[p->to]];
p->value -= mini[id[p->to]].cost; //到达除root外所有点的边的权值都要变化
if (j != -1 && j == new_id[id[i]]) p->flag = false; //去掉产生的新的自环
}
p = p->next;
}
}
for (i = 0; i < n; i++) {
j = new_id[id[i]];
if (j != -1) id[i] = j; //每个点的id可能会产生变化
}
}
}
return sum;
}
void add(int a, int b, double dis) {
if (fabs(dis) < eps) return ;
array[amount].to = b;
array[amount].value = dis;
array[amount].flag = true;
array[amount].next = graph[a];
graph[a] = &array[amount++];
}
int main() {
int n, m, i, s, e;
int data[scale][2];
double ans;
while (scanf("%d %d", &n, &m) != EOF) {
for (i = 0; i < n; i++) {
scanf("%d %d", &data[i][0], &data[i][1]);
graph[i] = NULL;
}
if (true) amount = 0;
for (i = 0; i < m; i++) {
scanf("%d %d", &s, &e);
s--;
e--;
add(s, e, sqrt(0.0+(data[s][1]-data[e][1])*(data[s][1]-data[e][1])+(data[s][0]-data[e][0])*(data[s][0]-data[e][0])));
}
ans = zhuliu(n, 0);
if (fabs(ans + 1) < eps) printf("poor snoopy\n");
else printf("%.2f\n", ans);
}
return 0;
}