Problem p03882 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>

#define _overload(_1, _2, _3, name, ...) name
#define _rep(i, n) _range(i, 0, n)
#define _range(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(...) _overload(__VA_ARGS__, _range, _rep, )(__VA_ARGS__)

#define _rrep(i, n) _rrange(i, n, 0)
#define _rrange(i, a, b) for (int i = int(a) - 1; i >= int(b); --i)
#define rrep(...) _overload(__VA_ARGS__, _rrange, _rrep, )(__VA_ARGS__)

#define _all(arg) begin(arg), end(arg)
#define uniq(arg) sort(_all(arg)), (arg).erase(unique(_all(arg)), end(arg))
#define getidx(ary, key) lower_bound(_all(ary), key) - begin(ary)
#define clr(a, b) memset((a), (b), sizeof(a))
#define bit(n) (1LL << (n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template <class T> bool chmax(T &a, const T &b) {
  return (a < b) ? (a = b, 1) : 0;
}
template <class T> bool chmin(T &a, const T &b) {
  return (b < a) ? (a = b, 1) : 0;
}

using ll = long long;
using R = long double;
const R EPS = 1e-9L; // [-1000,1000]->EPS=1e-8 [-10000,10000]->EPS=1e-7
inline int sgn(const R &r) { return (r > EPS) - (r < -EPS); }
inline R sq(R x) { return sqrt(max(x, 0.0L)); }

const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

// Problem Specific Parameter:
#define error(args...)                                                         \\
  {                                                                            \\
    vector<string> _debug = split(#args, ',');                                 \\
    err(begin(_debug), args);                                                  \\
  }

vector<string> split(const string &s, char c) {
  vector<string> v;
  stringstream ss(s);
  string x;
  while (getline(ss, x, c))
    v.emplace_back(x);
  return move(v);
}

void err(vector<string>::iterator it) { cerr << endl; }
template <typename T, typename... Args>
void err(vector<string>::iterator it, T a, Args... args) {
  cerr << it->substr((*it)[0] == ' ', it->length()) << " = " << a << " ",
      err(++it, args...);
}

// Description: 素集合を管理するデータ構造
// TimeComplexity: 初期化$\\mathcal{O}(n)$ 更新$\\mathcal{O}(\\log n)$
// Verifyed: AOJ DSL_1_A

struct Union_find {
  Union_find(int n) { data.assign(n, -1); }
  int find(int x) { return (data[x] < 0) ? x : data[x] = find(data[x]); }
  void unite(int a, int b) {
    a = find(a), b = find(b);
    if (a != b) {
      if (data[a] < data[b])
        swap(a, b);
      data[a] += data[b], data[b] = a;
    }
  }
  bool same(int a, int b) { return find(a) == find(b); }
  int size(int x) { return -data[x]; }
  vector<int> data;
};

int x[15], y[15], a[15];
bool dp[1 << 15];
R cost[1 << 15];

bool check(int n, R val) {
  rep(mask, 1 << n) {
    dp[mask] = false;
    const R m = __builtin_popcountll(mask);
    R cur = 0.0;
    rep(i, n) if (mask & (1 << i)) cur += a[i];
    cur -= cost[mask] + m * val;
    if (cur >= 0.0)
      dp[mask] = true;
    // error(mask, dp[mask]);
  }

  rep(mask, 1 << n) {
    if (dp[mask])
      continue;
    for (int smask = (mask - 1) & mask;; smask = (smask - 1) & mask) {
      const int tmask = mask ^ smask;
      if (smask < tmask)
        break;

      if (dp[smask] and dp[tmask]) {
        dp[mask] = true;
        break;
      }
    }
  }

  return dp[(1 << n) - 1];
}

int main(void) {
  int n;
  cin >> n;

  rep(i, n) cin >> x[i] >> y[i] >> a[i];

  using edge = tuple<R, int, int>;
  vector<edge> ary;

  rep(j, n) rep(i, j)
      ary.push_back(edge(hypot(x[i] - x[j], y[i] - y[j]), i, j));
  sort(begin(ary), end(ary));

  rep(mask, 1 << n) {
    cost[mask] = 0.0;
    Union_find uf(n);

    for (auto &e : ary) {
      R w;
      int a, b;
      tie(w, a, b) = e;
      if (((mask >> a) & 1) == 0)
        continue;
      if (((mask >> b) & 1) == 0)
        continue;
      if (uf.same(a, b))
        continue;
      cost[mask] += w;
      uf.unite(a, b);
    }
    // error(mask, cost[mask]);
  }

  R low = 0.0, high = 1e10;

  rep(loop, 100) {
    const R mid = (low + high) / 2.0;
    if (check(n, mid))
      low = mid;
    else
      high = mid;
  }

  cout.precision(20);
  cout << fixed << low << endl;

  /*
  cerr << check(n, 5.5) << endl;
  cerr << check(n, 7.5) << endl;
  */

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

#define _overload(_1, _2, _3, name, ...) name
#define _rep(i, n) _range(i, 0, n)
#define _range(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(...) _overload(__VA_ARGS__, _range, _rep, )(__VA_ARGS__)

#define _rrep(i, n) _rrange(i, n, 0)
#define _rrange(i, a, b) for (int i = int(a) - 1; i >= int(b); --i)
#define rrep(...) _overload(__VA_ARGS__, _rrange, _rrep, )(__VA_ARGS__)

#define _all(arg) begin(arg), end(arg)
#define uniq(arg) sort(_all(arg)), (arg).erase(unique(_all(arg)), end(arg))
#define getidx(ary, key) lower_bound(_all(ary), key) - begin(ary)
#define clr(a, b) memset((a), (b), sizeof(a))
#define bit(n) (1LL << (n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template <class T> bool chmax(T &a, const T &b) {
  return (a < b) ? (a = b, 1) : 0;
}
template <class T> bool chmin(T &a, const T &b) {
  return (b < a) ? (a = b, 1) : 0;
}

using ll = long long;
using R = long double;
const R EPS = 1e-9L; // [-1000,1000]->EPS=1e-8 [-10000,10000]->EPS=1e-7
inline int sgn(const R &r) { return (r > EPS) - (r < -EPS); }
inline R sq(R x) { return sqrt(max(x, 0.0L)); }

const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

// Problem Specific Parameter:
#define error(args...)                                                         \\
  {                                                                            \\
    vector<string> _debug = split(#args, ',');                                 \\
    err(begin(_debug), args);                                                  \\
  }

vector<string> split(const string &s, char c) {
  vector<string> v;
  stringstream ss(s);
  string x;
  while (getline(ss, x, c))
    v.emplace_back(x);
  return move(v);
}

void err(vector<string>::iterator it) { cerr << endl; }
template <typename T, typename... Args>
void err(vector<string>::iterator it, T a, Args... args) {
  cerr << it->substr((*it)[0] == ' ', it->length()) << " = " << a << " ",
      err(++it, args...);
}

// Description: 素集合を管理するデータ構造
// TimeComplexity: 初期化$\\mathcal{O}(n)$ 更新$\\mathcal{O}(\\log n)$
// Verifyed: AOJ DSL_1_A

struct Union_find {
  Union_find(int n) { data.assign(n, -1); }
  int find(int x) { return (data[x] < 0) ? x : data[x] = find(data[x]); }
  void unite(int a, int b) {
    a = find(a), b = find(b);
    if (a != b) {
      if (data[a] < data[b])
        swap(a, b);
      data[a] += data[b], data[b] = a;
    }
  }
  bool same(int a, int b) { return find(a) == find(b); }
  int size(int x) { return -data[x]; }
  vector<int> data;
};

int x[15], y[15], a[15];
bool dp[1 << 15];
R cost[1 << 15];

bool check(int n, R val) {
  rep(mask, 1 << n) {
    dp[mask] = false;
    const R m = __builtin_popcountll(mask);
    R cur = 0.0;
    rep(i, n) if (mask & (1 << i)) cur += a[i];
    cur -= cost[mask] + m * val;
    if (cur >= 0.0)
      dp[mask] = true;
    // error(mask, dp[mask]);
  }

  rep(mask, 1 << n) {
    if (dp[mask])
      continue;
    for (int smask = (mask - 1) & mask; smask > 0; smask = (smask - 1) & mask) {
      const int tmask = mask ^ smask;
      if (dp[smask] and dp[tmask]) {
        dp[mask] = true;
        break;
      }
    }
  }

  return dp[(1 << n) - 1];
}

int main(void) {
  int n;
  cin >> n;

  rep(i, n) cin >> x[i] >> y[i] >> a[i];

  rep(mask, 1 << n) {
    cost[mask] = 0.0;
    using edge = tuple<R, int, int>;
    vector<edge> ary;

    rep(j, n) rep(i, j) {
      if (((mask >> i) & 1) == 0)
        continue;
      if (((mask >> j) & 1) == 0)
        continue;
      ary.push_back(edge(hypot(x[i] - x[j], y[i] - y[j]), i, j));
    }

    sort(begin(ary), end(ary));
    Union_find uf(n);

    for (auto &e : ary) {
      R w;
      int a, b;
      tie(w, a, b) = e;
      if (uf.same(a, b))
        continue;
      cost[mask] += w;
      uf.unite(a, b);
    }
    // error(mask, cost[mask]);
  }

  R low = 0.0, high = 1e10;

  rep(loop, 100) {
    const R mid = (low + high) / 2.0;
    if (check(n, mid))
      low = mid;
    else
      high = mid;
  }

  cout.precision(20);
  cout << fixed << low << endl;

  /*
  cerr << check(n, 5.5) << endl;
  cerr << check(n, 7.5) << endl;
  */

  return 0;
}