#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int maxn = 1E2 + 10; const int INF = 1 << 30; struct Edge { int u, v; double w; }; Edge edge[maxn * maxn]; struct Node { double x, y; }; Node node[maxn]; double Get_Dist(int a, int b) { double d1 = (node[a].x - node[b].x) * (node[a].x - node[b].x); double d2 = (node[a].y - node[b].y) * (node[a].y - node[b].y); return sqrt(d1 + d2); } int n, m, pre[maxn], vis[maxn], id[maxn]; double in[maxn]; double DMST(int root, int n, int m) { double res = 0; int u, v; while (true) { //memset(in, INF, sizeof(in)); for (int i = 0; i < n; i++) in[i] = INF; memset(id, -1, sizeof(id)); memset(vis, -1, sizeof(vis)); for (int i = 0; i < m; i++) if (edge[i].u != edge[i].v && edge[i].w < in[edge[i].v]) { pre[edge[i].v] = edge[i].u; in[edge[i].v] = edge[i].w; } for (int i = 0; i < n; i++) if (i != root && in[i] == INF) return -1; int tn = 0; in[root] = 0; for (int i = 0; i < n; i++) { res += in[i]; v = i; while (vis[v] != i && id[v] == -1 && v != root) vis[v] = i, v = pre[v]; if (v != root && id[v] == -1) { for (int u = pre[v]; u != v; u = pre[u]) id[u] = tn; id[v] = tn++; } } if (tn == 0) break; for (int i = 0; i < n; i++) if (id[i] == -1) id[i] = tn++; for (int i = 0; i < m;) { v = edge[i].v; edge[i].u = id[edge[i].u]; edge[i].v = id[edge[i].v]; if (edge[i].u != edge[i].v) edge[i++].w -= in[v]; else swap(edge[i], edge[--m]); } n = tn; root = id[root]; } return res; } int main(int argc, char const *argv[]) { while (~scanf("%d%d", &n, &m)) { for (int i = 0; i < n; i++) scanf("%lf%lf", &node[i].x, &node[i].y); for (int i = 0; i < m; i++) { scanf("%d%d", &edge[i].u, &edge[i].v); edge[i].u--, edge[i].v--; edge[i].w = edge[i].u == edge[i].v ? INF : Get_Dist(edge[i].u, edge[i].v); } double ans = DMST(0, n, m); if (ans == -1) printf("poor snoopy\n"); else printf("%.2lf\n", ans); } return 0; }
最小树形图的模板题。