題目簡介
n個點,m條邊的圖,要使得圖中沒有圈,求要去掉的邊的權值和的最小值。
說明
求圖的最大生成樹,用總權值減生成樹權值得到答案。似乎是隻能用kruskal做。邊數組應該是要開到10000 * 10000 / 2的,沒想到eoj上提交rte,改成10000 * 100就好了……
#include <bits/stdc++.h>
using namespace std;
#define maxn 11000
struct edge
{
int u, v;
double w;
}g[maxn*100];
struct node
{
double x, y;
}point[maxn];
double sum;
int n, m, fa[maxn];
inline double dis(const node& a, const node& b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(const edge& a, const edge& b)
{
return a.w > b.w;
}
inline int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
inline double kruskal()
{
sort(g, g+m, cmp);
double remain = 0.0;
for (int i = 0; i < m; ++i)
{
int x = find(g[i].u), y = find(g[i].v);
if (x != y)
{
fa[x] = y;
remain += g[i].w;
}else continue;
}
return sum - remain;
}
int main()
{
int u, v;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
fa[i] = i;
for (int i = 1; i <= n; ++i)
scanf("%lf%lf", &point[i].x, &point[i].y);
for (int i = 0; i < m; ++i)
{
scanf("%d%d", &u, &v);
g[i].u = u;
g[i].v = v;
g[i].w = dis(point[u], point[v]);
sum += g[i].w;
}
printf("%.6f\n", kruskal());
return 0;
}