Cod sursa(job #1052177)

Utilizator ViksenVictor-Nicolae Savu Viksen Data 10 decembrie 2013 21:57:56
Problema Arbore partial de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.18 kb

#include <fstream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

size_t PrimeAncestor(const std::vector<size_t>& Parent, size_t n)
{
  while (Parent[n] != n) n = Parent[n];
  return n;
}

/**
  @brief Kruskal's Minimum Spanning Tree (MST) algorithm with disjoint set forests
*/
template<typename ContainerT, typename GetFormerVertexF, typename GetLatterVertexF, typename OnMergeF> std::vector<size_t>
KruskalMST(const ContainerT& OrderedEdges, GetFormerVertexF former, GetLatterVertexF latter, size_t N, OnMergeF on_merge)
{
  std::vector<size_t> Parent(N);
  std::vector<size_t> MaxDepth(N, 0);
  size_t i = 0;

  // initially, the MST has no edges
  for (auto& p : Parent) p = i++;

  // add edges to the MST as long as they maintain the tree property
  for (const auto& edge : OrderedEdges) {
    size_t a = PrimeAncestor(Parent, former(edge));
    size_t b = PrimeAncestor(Parent, latter(edge));
    if (a != b) {
      if (on_merge(edge, a, b)) {
        if (MaxDepth[a] < MaxDepth[b]) Parent[a] = b;
        else if (MaxDepth[a] > MaxDepth[b]) Parent[b] = a;
        else { ++MaxDepth[a]; Parent[b] = a; }
      }
    }
  }

  return Parent;
}

int main()
{
  ifstream in("apm.in", ios::in);
  ofstream out("apm.out", ios::out);

  size_t n, m;
  in >> n >> m;

  vector<tuple<int, size_t, size_t>> edges; edges.reserve(m);
  for (size_t i=0; i < m; ++i) {
    size_t a, b;
    int c;
    in >> a >> b >> c;
    edges.emplace_back(c, a, b);
  }
  sort(begin(edges), end(edges), [](const tuple<int, size_t, size_t>& a, const tuple<int, size_t, size_t>& b) -> bool {
    return get<0>(a) < get<0>(b);
  });

  int cost = 0;
  vector<pair<size_t, size_t>> tree; tree.reserve(n-1);

  auto former = [](tuple<int, size_t, size_t> e)-> size_t { return get<1>(e); };
  auto latter = [](tuple<int, size_t, size_t> e)-> size_t { return get<2>(e); };
  auto on_merge = [&tree, &cost](tuple<int, size_t, size_t> e, size_t, size_t) { tree.emplace_back(get<1>(e), get<2>(e)); cost += get<0>(e); return true; };

  KruskalMST(edges, former, latter, n, on_merge);

  out << cost << '\n' << n-1 << '\n';
  for (const auto& e : tree) out << e.first << ' ' << e.second << '\n';

  out.close();
  return 0;
}