题意:求有向图的最小生成树。
题解:最小树形图
模板题。
注意几点:
①double
②自环重边
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1010;
const int MAXM = 40010;
struct Edge {
int u, v;
double cost;
}edge[MAXM];
int pre[MAXN], id[MAXN], vis[MAXN];
double in[MAXN];
double zhuliu(int rt, int n, int m) {
int u, v;
double res = 0;
while (1) {
for (int i = 0; i < n; i++) in[i] = INF;
for (int i = 0; i < m; i++)
if (edge[i].u != edge[i].v && edge[i].cost < in[edge[i].v]) {
pre[edge[i].v] = edge[i].u;
in[edge[i].v] = edge[i].cost;
}
for (int i = 0; i < n; i++)
if (i != rt && in[i] == INF) return -1;//不存在最小树形图
int tn = 0;
memset(id, -1, sizeof(id));
memset(vis, -1, sizeof(vis));
in[rt] = 0;
for (int i = 0; i < n; i++) {
res += in[i];
v = i;
while (vis[v] != i && id[v] == -1 && v != rt) {
vis[v] = i;
v = pre[v];
}
if (v != rt && 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++].cost -= in[v];
else swap(edge[i], edge[--m]);
}
n = tn;
rt = id[rt];
}
return res;
}
int n, m;
double g[MAXN][MAXN], x[MAXN], y[MAXN];
double dis(double xa, double ya, double xb, double yb) {
return sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
}
int main() {
while (~scanf("%d%d", &n, &m)) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
g[i][j] = INF;
}
}
for (int i = 0; i < n; i++) scanf("%lf%lf", &x[i], &y[i]);
int u, v;
while (m--) {
scanf("%d%d", &u, &v); u--, v--;
if (u == v)continue;
//cout << g[u][v] << endl;
g[u][v] = min(g[u][v], dis(x[u], y[u], x[v], y[v]));
}
int L = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (g[i][j] < INF) {
edge[L].u = i;
edge[L].v = j;
edge[L++].cost = g[i][j];
//cout << 1;
}
double ans = zhuliu(0, n, L);
if (ans == -1) puts("poor snoopy");
else printf("%.2f\n", ans);
}
return 0;
}