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

#include <bits/stdc++.h>
using namespace std;
int p[51], r[51];
void init() {
  for (int i = 0; i < 50; i++)
    p[i] = i, r[i] = 0;
}
int find(int x) { return (p[x] == x) ? x : (p[x] = find(p[x])); }
void unite(int x, int y) {
  x = find(x), y = find(y);
  if (x == y)
    return;
  if (r[x] < r[y])
    p[x] = y;
  else {
    p[y] = x;
    if (r[x] == r[y])
      r[x]++;
  }
}
bool same(int x, int y) { return find(x) == find(y); }
vector<string> s, ans;
set<string> se[50];
int n, m;

void dfs(int k, int t) {
  bool f = 1;
  for (int i = 1; i < m; i++)
    if (!same(0, i))
      f = 0;
  if (f) {
    if (!ans.size() || ans.size() > __builtin_popcount(t)) {
      ans.clear();
      for (int i = 0; i < n; i++) {
        if (t & (1 << i))
          ans.push_back(s[i]);
      }
    }
    return;
  }
  if (k >= n)
    return;
  for (int i = k; i < n; i++) {
    if (__builtin_popcount(t | (1 << i)) > 5)
      continue;
    int l = 0;
    while (l < m && !se[l].count(s[i]))
      l++;
    if (l == m)
      continue;
    int pp[m], rr[m];
    for (int j = 0; j < m; j++)
      pp[j] = p[j], rr[j] = r[j];
    for (int j = l + 1; j < m; j++) {
      if (se[j].count(s[i]))
        unite(l, j);
    }
    dfs(i + 1, t | (1 << i));
    for (int j = 0; j < m; j++)
      p[j] = pp[j], r[j] = rr[j];
  }
}

int main() {
  int f = 0;
  while (cin >> n >> m && n) {
    if (f)
      cout << endl;
    f = 1;
    init();
    ans.clear();
    s.clear();
    for (int i = 0; i < n; i++) {
      string t;
      cin >> t;
      s.push_back(t);
    }
    for (int i = 0; i < m; i++) {
      se[i].clear();
      int k;
      cin >> k;
      for (int j = 0; j < k; j++) {
        string t;
        cin >> t;
        se[i].insert(t);
      }
    }
    dfs(0, 0);
    if (ans.size()) {
      cout << ans.size() << endl;
      for (int i = 0; i < ans.size(); i++)
        cout << ans[i] << endl;
    } else
      cout << "Impossible" << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
int p[51], r[51];
void init() {
  for (int i = 0; i < 50; i++)
    p[i] = i, r[i] = 0;
}
int find(int x) { return (p[x] == x) ? x : (p[x] = find(p[x])); }
void unite(int x, int y) {
  x = find(x), y = find(y);
  if (x == y)
    return;
  if (r[x] < r[y])
    p[x] = y;
  else {
    p[y] = x;
    if (r[x] == r[y])
      r[x]++;
  }
}
bool same(int x, int y) { return find(x) == find(y); }
vector<string> s, ans;
set<string> se[50];
int n, m;

void dfs(int k, int t) {
  if (__builtin_popcount(t) > 5)
    return;
  bool f = 1;
  for (int i = 1; i < m; i++)
    if (!same(0, i))
      f = 0;
  if (f) {
    if (!ans.size() || ans.size() > __builtin_popcount(t)) {
      ans.clear();
      for (int i = 0; i < n; i++) {
        if (t & (1 << i))
          ans.push_back(s[i]);
      }
    }
    return;
  }
  if (k >= n)
    return;
  for (int i = k; i < n; i++) {
    int l = 0;
    while (l < m && !se[l].count(s[i]))
      l++;
    if (l == m)
      continue;
    int pp[m], rr[m];
    for (int j = 0; j < m; j++)
      pp[j] = p[j], rr[j] = r[j];
    for (int j = l + 1; j < m; j++) {
      if (se[j].count(s[i]))
        unite(l, j);
    }
    dfs(i + 1, t | (1 << i));
    for (int j = 0; j < m; j++)
      p[j] = pp[j], r[j] = rr[j];
  }
}

int main() {
  int f = 0;
  while (cin >> n >> m && n) {
    if (f)
      cout << endl;
    f = 1;
    init();
    ans.clear();
    s.clear();
    for (int i = 0; i < n; i++) {
      string t;
      cin >> t;
      s.push_back(t);
    }
    for (int i = 0; i < m; i++) {
      se[i].clear();
      int k;
      cin >> k;
      for (int j = 0; j < k; j++) {
        string t;
        cin >> t;
        se[i].insert(t);
      }
    }
    dfs(0, 0);
    if (ans.size()) {
      cout << ans.size() << endl;
      for (int i = 0; i < ans.size(); i++)
        cout << ans[i] << endl;
    } else
      cout << "Impossible" << endl;
  }
  return 0;
}