码迷,mamicode.com
首页 > 其他好文 > 详细

AOJ 2224 Save your cats (Kruskal)

时间:2017-08-21 00:13:30      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:poi   rom   red   最大生成树   ++i   tco   isp   最大   题意   

题意:给出一个图,去除每条边的花费为边的长度,求用最少的花费去除部分边使得图中无圈。

思路:先将所有的边长加起来,然后减去最大生成树,即得出最小需要破坏的篱笆长度。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;

int N, M; // 桩数量,篱笆数量
int par[10005];
void init() {
	for (int i = 1; i <= N; ++i) par[i] = i;
}
int find(int x) {
	return x == par[x] ? x : par[x] = find(par[x]);
}
bool same(int x, int y) {
	return find(x) == find(y);
}
void unite(int x, int y) {
	x = find(x);
	y = find(y);
	if (x != y) par[x] = y;
}

struct point{
	int x, y;
} ps[10005];

double dist(point &p1, point &p2) {
	return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}

struct edge {
	int from, to;
	double cost;
	edge(int from, int to, double cost) : from(from), to(to), cost(cost) {}
	bool operator<(const edge &b) const { // 从大到小排序,求出最大生成树
		return cost > b.cost;
	}
};

vector<edge> es; // 边集
double ans = 0.0; // 答案

void kruskal() {
	init();
	sort(es.begin(), es.end());
	for (auto it : es) { // C++11
		if (!same(it.from, it.to)) {
			unite(it.from, it.to);
			ans -= it.cost; // 减去最大生成树的边即可
		}
	}
}

void solve() {
	kruskal();
	printf("%.3lf\n", ans);
}

int main()
{
	cin >> N >> M;
	for (int i = 1; i <= N; ++i)
		cin >> ps[i].x >> ps[i].y;
	int u, v;
	double d;
	for (int i = 0; i < M; ++i) {
		cin >> u >> v;
		d = dist(ps[u], ps[v]);
		es.push_back(edge(u, v, d));
		ans += d; // 求出所有路径和
	}
	solve();
	return 0;
}

AOJ 2224 Save your cats (Kruskal)

标签:poi   rom   red   最大生成树   ++i   tco   isp   最大   题意   

原文地址:http://www.cnblogs.com/demian/p/7401770.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!