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

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

/**
 * hash???????????????UnionFind
 * ????´???°???16????????????????????¨??????????????????
 */
template <int N> struct SUnionFind {
  int i2g[N];
  SUnionFind() {
    for (int i = 0; i < N; i++) {
      i2g[i] = i;
    }
  }
  SUnionFind(ull hs) {
    for (int i = 0; i < N; i++) {
      i2g[i] = hs & 0xf;
      hs >>= 4;
    }
  }

  void merge(int x, int y) {
    int xg = i2g[x], yg = i2g[y];
    for (int i = 0; i < N; i++) {
      if (i2g[i] == yg)
        i2g[i] = xg;
    }
  }

  bool same(int x, int y) { return i2g[x] == i2g[y]; }

  ull hash() {
    int b[N];
    memset(b, -1, sizeof(b));
    int c = 0;
    ull hs = 0;
    for (int i = N - 1; i >= 0; i--) {
      hs <<= 4;
      if (b[i2g[i]] == -1) {
        b[i2g[i]] = c;
        c++;
      }
      hs += b[i2g[i]];
    }
    return hs;
  }
};

typedef SUnionFind<14> UF;
typedef pair<ull, double> P;

struct MyCmp {
  bool operator()(const P &l, const P &r) const { return l.first < r.first; }
};

int main() {
  int n, m, pp;
  cin >> n >> m >> pp;
  double p = pp / 100.0;

  int g[14] = {};
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    if (a > b)
      swap(a, b);
    g[a] |= (1 << b);
  }

  vector<P> mp;
  mp.push_back(P(UF().hash(), 1.0));
  for (int i = 0; i < n - 1; i++) {
    for (int j = i + 1; j < n; j++) {
      if (!(g[i] & (1 << j)))
        continue;
      mp.reserve(mp.size() * 2);
      int S = (int)mp.size();
      for (int k = 0; k < S; k++) {
        ull d;
        double r;
        tie(d, r) = mp[k];
        UF uf(d);
        uf.merge(i, j);
        mp[k].second *= p;
        mp.push_back(P(uf.hash(), r * (1 - p)));
      }
      if (!mp.size())
        continue;
      sort(mp.begin(), mp.end(), MyCmp());
      int l = 0;
      for (int k = 1; k < (int)mp.size(); k++) {
        if (mp[l].first != mp[k].first) {
          l++;
          mp[l] = mp[k];
        } else {
          mp[l].second += mp[k].second;
        }
      }
      l++;
      mp.resize(l);
    }

    int nn = 0;
    int S = (int)mp.size();
    for (int k = 0; k < S; k++) {
      P p = mp[k];
      UF uf(p.first);
      bool f = false;
      for (int j = i + 1; j < n; j++) {
        if (uf.same(i, j)) {
          f = true;
          break;
        }
      }
      if (!f)
        continue;

      UF uf2;
      for (int j = i + 1; j < n; j++) {
        for (int k = j + 1; k < n; k++) {
          if (uf.same(j, k))
            uf2.merge(j, k);
        }
      }
      mp[nn] = P(uf2.hash(), p.second);
      nn++;
    }
    mp.resize(nn);
    if (!mp.size())
      continue;
    sort(mp.begin(), mp.end(), MyCmp());
    int l = 0;
    for (int k = 1; k < (int)mp.size(); k++) {
      if (mp[l].first != mp[k].first) {
        l++;
        mp[l] = mp[k];
      } else {
        mp[l].second += mp[k].second;
      }
    }
    l++;
    mp.resize(l);
  }
  double res = 0;
  for (auto p : mp) {
    res += p.second;
  }
  printf("%.20lf\\n", res);
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

/**
 * hash???????????????UnionFind
 * ????´???°???16????????????????????¨??????????????????
 */
template <int N> struct SUnionFind {
  int i2g[N];
  SUnionFind() {
    for (int i = 0; i < N; i++) {
      i2g[i] = i;
    }
  }
  SUnionFind(ull hs) {
    for (int i = 0; i < N; i++) {
      i2g[i] = hs & 0xf;
      hs >>= 4;
    }
  }

  void merge(int x, int y) {
    int xg = i2g[x], yg = i2g[y];
    for (int i = 0; i < N; i++) {
      if (i2g[i] == yg)
        i2g[i] = xg;
    }
  }

  bool same(int x, int y) { return i2g[x] == i2g[y]; }

  ull hash() {
    int b[N];
    memset(b, -1, sizeof(b));
    int c = 0;
    ull hs = 0;
    for (int i = N - 1; i >= 0; i--) {
      hs <<= 4;
      if (b[i2g[i]] == -1) {
        b[i2g[i]] = c;
        c++;
      }
      hs += b[i2g[i]];
    }
    return hs;
  }
};

typedef SUnionFind<14> UF;
typedef pair<ull, double> P;
int main() {
  int n, m, pp;
  cin >> n >> m >> pp;
  double p = pp / 100.0;

  int g[14] = {};
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    if (a > b)
      swap(a, b);
    g[a] |= (1 << b);
  }

  vector<P> mp;
  mp.push_back(P(UF().hash(), 1.0));
  for (int i = 0; i < n - 1; i++) {
    for (int j = i + 1; j < n; j++) {
      if (!(g[i] & (1 << j)))
        continue;
      //            cout << i << " " << j << " " << mp.size() << endl;
      //            cout << mp.capacity() << " " << mp2.capacity() << endl;
      mp.reserve(mp.size() * 2);
      int S = (int)mp.size();
      for (int k = 0; k < S; k++) {
        ull d;
        double r;
        tie(d, r) = mp[k];
        UF uf(d);
        uf.merge(i, j);
        mp[k].second *= p;
        mp.push_back(P(uf.hash(), r * (1 - p)));
      }
      if (!mp.size())
        continue;
      sort(mp.begin(), mp.end());
      int l = 0;
      for (int k = 1; k < (int)mp.size(); k++) {
        if (mp[l].first != mp[k].first) {
          l++;
          mp[l] = mp[k];
        } else {
          mp[l].second += mp[k].second;
        }
      }
      l++;
      mp.resize(l);
    }

    int nn = 0;
    int S = (int)mp.size();
    for (int k = 0; k < S; k++) {
      P p = mp[k];
      UF uf(p.first);
      bool f = false;
      for (int j = i + 1; j < n; j++) {
        if (uf.same(i, j)) {
          f = true;
          break;
        }
      }
      if (!f)
        continue;

      UF uf2;
      for (int j = i + 1; j < n; j++) {
        for (int k = j + 1; k < n; k++) {
          if (uf.same(j, k))
            uf2.merge(j, k);
        }
      }
      mp[nn] = P(uf2.hash(), p.second);
      nn++;
    }
    mp.resize(nn);
    if (!mp.size())
      continue;
    sort(mp.begin(), mp.end());
    int l = 0;
    for (int k = 1; k < (int)mp.size(); k++) {
      if (mp[l].first != mp[k].first) {
        l++;
        mp[l] = mp[k];
      } else {
        mp[l].second += mp[k].second;
      }
    }
    l++;
    mp.resize(l);
  }
  double res = 0;
  for (auto p : mp) {
    res += p.second;
  }
  //    cout << mp.capacity() << endl;
  printf("%.20lf\\n", res);
  return 0;
}