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

#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

using namespace std;

typedef long long ll;

class UnionFindTree {
private:
  // indexÌÌem[h( éWÌeð©Â¯½¢Æ«Í±±ð¼ÚQÆ¹¸Afindðg¤)
  vector<int> par;
  // indexðªÆ·éØÌN
  vector<int> rank;
  // ØÌÅål
  int treeSize;

public:
  UnionFindTree(int initTreeSize = 1000) {
    // øÅ^¦çê½lðÅåi[Æ·éUnionFindTreeÌì¬
    treeSize = initTreeSize;
    for (int i = 0; i < treeSize; i++) {
      par.push_back(i);
      rank.push_back(0);
    }
    init();
  }
  void init() {
    par.clear();
    rank.clear();
    for (int i = 0; i < treeSize; i++) {
      par[i] = i;
      rank[i] = 0;
    }
  }
  // ^¦çê½ªi[³êÄ¢éØÌ[gðTõ
  int find(int x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = find(par[x]);
  }
  // aWðÆéB½¾µ±±ÅÍeWÌeÌt¯Ö¦ÍN±çÈ¢
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (rank[x] < rank[y])
      par[x] = y;
    else {
      par[y] = x;
      if (rank[y] == rank[x])
        rank[x]++;
    }
  }

  bool same(int x, int y) { return find(x) == find(y); }
};

int N, M;
map<string, int> langNum;
string langs[100];
bool spkLanSet[101][101];
int spkLans[101];
int minCost;
int resLan[101];

int main() {
  bool fst = true;
  while (cin >> N >> M && (N | M)) {
    for (int i = 0; i < 101; i++)
      for (int j = 0; j < 101; j++)
        spkLanSet[i][j] = false;
    if (fst)
      fst = false;
    else
      cout << endl;
    minCost = 10;
    langNum.clear();
    for (int i = 0; i < N; i++) {
      cin >> langs[i];
      langNum[langs[i]] = i;
    }
    for (int i = 0; i < M; i++) {
      // spkLanSet[i].clear();
      int t;
      cin >> t;
      for (int j = 0; j < t; j++) {
        string s;
        cin >> s;
        spkLanSet[i][langNum[s]] = true;
      }
    }
    // SÄÌgÝí¹ð·
    int cnt = 0;
    UnionFindTree uft(M);
    for (int size = 1; size <= min(N, 5); size++) {
      ll comb = (1LL << size) - 1;
      while (comb < (1LL << N)) {
        cnt++;
        int c = 0;
        for (int i = 0; i < N; i++)
          if ((comb >> i) & (1LL))
            spkLans[c++] = i;
        // ±±Åsimulation
        {
          uft.init();
          for (int j = 0; j < size; j++) {
            int spPos = M;
            for (int k = 0; k < M; k++) {
              if (spkLanSet[k][spkLans[j]]) {
                spPos = k + 1;
                break;
              }
            }
            for (int k = spPos; k < M; k++) {
              if (spkLanSet[k][spkLans[j]]) {
                uft.unite(spPos - 1, k);
              }
            }
          }
          bool ok = true;
          for (int j = 1; j < M; j++) {
            if (!uft.same(0, j))
              ok = false;
          }
          if (ok) {
            if (minCost > size) {
              minCost = size;
              for (int j = 0; j < size; j++)
                resLan[j] = spkLans[j];
            }
          }
        }
        ll x = comb & -comb, y = comb + x;
        comb = ((comb & ~y) / x >> 1) | y;
      }
    }
    if (minCost == 10)
      cout << "Impossible" << endl;
    else {
      cout << minCost << endl;
      for (int i = 0; i < minCost; i++)
        cout << langs[resLan[i]] << endl;
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

using namespace std;

typedef long long ll;

class UnionFindTree {
private:
  // indexÌÌem[h( éWÌeð©Â¯½¢Æ«Í±±ð¼ÚQÆ¹¸Afindðg¤)
  vector<int> par;
  // indexðªÆ·éØÌN
  vector<int> rank;
  // ØÌÅål
  int treeSize;

public:
  UnionFindTree(int initTreeSize = 1000) {
    // øÅ^¦çê½lðÅåi[Æ·éUnionFindTreeÌì¬
    treeSize = initTreeSize;
    for (int i = 0; i < treeSize; i++) {
      par.push_back(i);
      rank.push_back(0);
    }
    init();
  }
  void init() {
    par.clear();
    rank.clear();
    for (int i = 0; i < treeSize; i++) {
      par[i] = i;
      rank[i] = 0;
    }
  }
  // ^¦çê½ªi[³êÄ¢éØÌ[gðTõ
  int find(int x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = find(par[x]);
  }
  // aWðÆéB½¾µ±±ÅÍeWÌeÌt¯Ö¦ÍN±çÈ¢
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (rank[x] < rank[y])
      par[x] = y;
    else {
      par[y] = x;
      if (rank[y] == rank[x])
        rank[x]++;
    }
  }

  bool same(int x, int y) { return find(x) == find(y); }
};

int N, M;
map<string, int> langNum;
string langs[100];
set<int> spkLanSet[101];
int spkLans[101];
int minCost;
int resLan[101];

int main() {
  bool fst = true;
  while (cin >> N >> M && (N | M)) {
    if (fst)
      fst = false;
    else
      cout << endl;
    minCost = 10;
    langNum.clear();
    for (int i = 0; i < N; i++) {
      cin >> langs[i];
      langNum[langs[i]] = i;
    }
    for (int i = 0; i < M; i++) {
      spkLanSet[i].clear();
      int t;
      cin >> t;
      for (int j = 0; j < t; j++) {
        string s;
        cin >> s;
        spkLanSet[i].insert(langNum[s]);
      }
    }
    // SÄÌgÝí¹ð·
    int cnt = 0;
    UnionFindTree uft(M);
    for (int size = 1; size <= min(N, 5); size++) {
      int comb = (1 << size) - 1;
      while (comb < (1 << N)) {
        cnt++;
        int c = 0;
        for (int i = 0; i < N; i++)
          if ((comb >> i) & (1))
            spkLans[c++] = i;
        // ±±Åsimulation
        {
          uft.init();
          for (int j = 0; j < size; j++) {
            int spPos = M;
            for (int k = 0; k < M; k++) {
              if (spkLanSet[k].count(spkLans[j]) > 0) {
                spPos = k + 1;
                break;
              }
            }
            for (int k = spPos; k < M; k++) {
              if (spkLanSet[k].count(spkLans[j]) > 0) {
                uft.unite(spPos - 1, k);
              }
            }
          }
          bool ok = true;
          for (int j = 1; j < M; j++) {
            if (!uft.same(0, j))
              ok = false;
          }
          if (ok) {
            if (minCost > size) {
              minCost = size;
              for (int j = 0; j < size; j++)
                resLan[j] = spkLans[j];
            }
          }
        }
        int x = comb & -comb, y = comb + x;
        comb = ((comb & ~y) / x >> 1) | y;
      }
    }
    if (minCost == 10)
      cout << "Impossible" << endl;
    else {
      cout << minCost << endl;
      for (int i = 0; i < minCost; i++)
        cout << langs[resLan[i]] << endl;
    }
    cout << cnt << endl;
  }

  return 0;
}