TopCoder SRM 687 Div1 Medium: AllGraphCuts

解法

Gomory-Hu 木が作れることからGomory-Hu 木が作れることは明らか。
kyuridenamida先生のコードを写経した。

コード

#include <bits/stdc++.h>
using namespace std;

struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) {}
  UnionFind(const UnionFind &u) { data = u.data; }
  bool unionSet(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
  bool is_same(int x, int y) { return findSet(x, y); }
};

class AllGraphCuts {
 public:
  vector<int> findGraph(vector<int> x) {
    int N = sqrt(x.size()) + 0.1;

    // check
    for (int i = 0; i < N; ++i)
      if (x[N * i + i] != 0) return {-1};

    map<int, vector<int>> es;
    set<int> w;
    for (int pos = 0; pos < N * N; ++pos) {
      int weight = x[pos];
      es[weight].push_back(pos);
      w.insert(weight);
    }

    UnionFind uf(N);
    vector<int> ans;
    for (auto rit = w.rbegin(); rit != w.rend(); ++rit) {
      int weight = *rit;
      for (auto pos : es[weight]) {
        int i = pos / N;
        int j = pos % N;
        if (i != j && uf.is_same(i, j)) return {-1};
      }

      for (auto pos : es[weight]) {
        int i = pos / N;
        int j = pos % N;
        if (!uf.is_same(i, j)) {
          ans.push_back(weight * N * N + i * N + j);
          uf.unionSet(i, j);
        }
      }
    }

    return ans;
  }
};