AOJ 2224 Save your cats (Kruskal)
阿新 • • 發佈:2017-08-21
one sort con -c namespace iter ott cst cin
題意:給出一個圖,去除每條邊的花費為邊的長度,求用最少的花費去除部分邊使得圖中無圈。
思路:先將所有的邊長加起來,然後減去最大生成樹,即得出最小需要破壞的籬笆長度。
#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)