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

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
void chmin(int &a, int b) { a = min(a, b); }

#define EPS (1e-7)
#define INF (1e9)
#define PI (acos(-1))
// const ll mod = 1000000007;
struct UnionFind {
  vector<int> par;
  vector<int> rank;
  vector<ll> Size;
  UnionFind(int n = 1) { init(n); }

  void init(int n = 1) {
    par.resize(n + 1);
    rank.resize(n + 1);
    Size.resize(n + 1);
    for (int i = 0; i <= n; ++i)
      par[i] = i, rank[i] = 0, Size[i] = 1;
  }

  int root(int x) {
    if (par[x] == x) {
      return x;
    } else {
      int r = root(par[x]);
      return par[x] = r;
    }
  }

  bool issame(int x, int y) { return root(x) == root(y); }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (rank[x] < rank[y])
      swap(x, y);
    if (rank[x] == rank[y])
      ++rank[x];
    par[y] = x;
    Size[x] += Size[y];
    return true;
  }

  ll size(int x) { return Size[root(x)]; }
};

int N;
unordered_map<string, int> mp;
set<string> st;
string intersection[1005];
string before[1005], after[1005];
string name[205];
int dist[205][205];
bool beforei[205][205], afteri[205][205];
int main() {
  // cout.precision(10);
  cin.tie(0);
  ios::sync_with_stdio(false);
  UnionFind uni;
  int timer = 0;
  while (true) {
    timer++;
    // cerr << timer << endl;
    uni.init(500);
    st.clear();
    mp.clear();
    cin >> N;
    if (N == 0)
      break;
    for (int i = 1; i <= N; i++) {
      cin >> intersection[i];
      int moji = 0;
      while (intersection[i][moji] != '-')
        moji++;
      before[i] = intersection[i].substr(0, moji);
      after[i] = intersection[i].substr(moji + 1);
      st.insert(before[i]);
      st.insert(after[i]);
      // cerr << before[i] << " " << after[i] << endl;
    }
    int num = 0;
    for (auto itr = st.begin(); itr != st.end(); itr++) {
      num++;
      mp[*itr] = num;
      name[num] = *itr;
    }
    for (int i = 1; i <= num; i++) {
      for (int j = 1; j <= num; j++)
        beforei[i][j] = false, afteri[i][j] = false;
      for (int k = 1; k <= N; k++) {
        if (mp[before[k]] == i)
          afteri[i][mp[after[k]]] = true;
        if (mp[after[k]] == i)
          beforei[i][mp[before[k]]] = true;
      }
    }
    for (int i = 1; i <= num; i++) {
      for (int j = i + 1; j <= num; j++) {
        /*
        cerr << "----" << i << "----" << endl;
        for(int k = 1; k <= num; k++) {
            cerr << k << " " << beforei[k] << " " << afteri[k] << endl;
        }
        */
        bool isok = false;
        for (int k = 1; k <= num; k++) {
          if (beforei[i][k] && beforei[j][k])
            isok = true;
          if (afteri[i][k] && afteri[j][k])
            isok = true;
        }
        if (!isok)
          continue;
        for (int k = 1; k <= num; k++) {
          if (beforei[i][k] && afteri[j][k])
            isok = false;
          if (beforei[j][k] && afteri[i][k])
            isok = false;
        }
        if (isok)
          uni.merge(i, j);
      }
    }
    /*
    for(int i = 1; i <= num; i++) {
        cerr << i << " " << name[i] << " " << uni.root(i) << endl;
    }
    */
    for (int i = 1; i <= num; i++) {
      for (int j = 1; j <= num; j++) {
        dist[i][j] = INF;
      }
      dist[i][i] = 0;
    }
    /*
    UnionFind uni2(1000);
    for(int i = 1; i <= N; i++) {
        uni2.merge(mp[before[i]], mp[after[i]] + 200);
        uni2.merge(mp[before[i]] + 200, mp[after[i]]);
        dist[mp[before[i]]][mp[after[i]]] = 1;
    }
    */
    for (int i = 1; i <= N; i++) {
      dist[uni.root(mp[before[i]])][uni.root(mp[after[i]])] = 1;
    }
    for (int i = 1; i <= num; i++) {
      for (int j = 1; j <= num; j++) {
        for (int k = 1; k <= num; k++) {
          chmin(dist[j][k], dist[j][i] + dist[i][k]);
        }
      }
    }
    /*
    for(int i = 1; i <= num; i++) {
        for(int j = 1; j <= num; j++) cerr << dist[i][j] << " ";
        cerr << endl;
    }
    */
    int M;
    cin >> M;
    cout << st.size() << endl;
    while (M--) {
      string in;
      cin >> in;
      string a, b;
      int moji = 0;
      while (in[moji] != '-')
        moji++;
      a = in.substr(0, moji);
      b = in.substr(moji + 1);
      if (st.find(a) == st.end() || st.find(b) == st.end()) {
        cout << "NO" << endl;
        continue;
      }
      a = name[uni.root(mp[a])];
      b = name[uni.root(mp[b])];
      // cerr << a << " " << mp[a] << " " << b << " " << mp[b] << endl;
      /*
      if(!uni2.issame(mp[a], mp[b] + 200)) {
          //cerr << "NOT CONNECTED" << endl;
          cout << "NO" << endl;
          continue;
      }
      */
      // cerr << dist[mp[a]][mp[b]] << endl;
      if (dist[mp[a]][mp[b]] == INF)
        cout << "NO" << endl;
      else if (dist[mp[a]][mp[b]] % 2 == 0)
        cout << "NO" << endl;
      else
        cout << "YES" << endl;
    }
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
void chmin(int &a, int b) { a = min(a, b); }

#define EPS (1e-7)
#define INF (1e9)
#define PI (acos(-1))
// const ll mod = 1000000007;
struct UnionFind {
  vector<int> par;
  vector<int> rank;
  vector<ll> Size;
  UnionFind(int n = 1) { init(n); }

  void init(int n = 1) {
    par.resize(n + 1);
    rank.resize(n + 1);
    Size.resize(n + 1);
    for (int i = 0; i <= n; ++i)
      par[i] = i, rank[i] = 0, Size[i] = 1;
  }

  int root(int x) {
    if (par[x] == x) {
      return x;
    } else {
      int r = root(par[x]);
      return par[x] = r;
    }
  }

  bool issame(int x, int y) { return root(x) == root(y); }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (rank[x] < rank[y])
      swap(x, y);
    if (rank[x] == rank[y])
      ++rank[x];
    par[y] = x;
    Size[x] += Size[y];
    return true;
  }

  ll size(int x) { return Size[root(x)]; }
};

int N;
map<string, int> mp;
set<string> st;
string intersection[1005];
string before[1005], after[1005];
string name[205];
int dist[205][205];
int main() {
  // cout.precision(10);
  cin.tie(0);
  ios::sync_with_stdio(false);
  UnionFind uni;
  while (true) {
    uni.init(500);
    st.clear();
    mp.clear();
    cin >> N;
    if (N == 0)
      break;
    for (int i = 1; i <= N; i++) {
      cin >> intersection[i];
      int moji = 0;
      while (intersection[i][moji] != '-')
        moji++;
      before[i] = intersection[i].substr(0, moji);
      after[i] = intersection[i].substr(moji + 1);
      st.insert(before[i]);
      st.insert(after[i]);
      // cerr << before[i] << " " << after[i] << endl;
    }
    int num = 0;
    for (auto itr = st.begin(); itr != st.end(); itr++) {
      num++;
      mp[*itr] = num;
      name[num] = *itr;
    }
    for (int i = 1; i <= num; i++) {
      for (int j = i + 1; j <= num; j++) {
        bool beforei[205], afteri[205], beforej[205], afterj[205];
        for (int i = 1; i <= num; i++) {
          beforei[i] = false;
          beforej[i] = false;
          afteri[i] = false;
          afterj[i] = false;
        }
        for (int k = 1; k <= N; k++) {
          if (mp[before[k]] == i)
            afteri[mp[after[k]]] = true;
          if (mp[before[k]] == j)
            afterj[mp[after[k]]] = true;
          if (mp[after[k]] == i)
            beforei[mp[before[k]]] = true;
          if (mp[after[k]] == j)
            beforej[mp[before[k]]] = true;
        }
        /*
        cerr << "----" << i << "----" << endl;
        for(int k = 1; k <= num; k++) {
            cerr << k << " " << beforei[k] << " " << afteri[k] << endl;
        }
        */
        bool isok = false;
        for (int k = 1; k <= num; k++) {
          if (beforei[k] && beforej[k])
            isok = true;
          if (afteri[k] && afterj[k])
            isok = true;
        }
        if (!isok)
          continue;
        for (int k = 1; k <= num; k++) {
          if (beforei[k] && afterj[k])
            isok = false;
          if (beforej[k] && afteri[k])
            isok = false;
        }
        if (isok)
          uni.merge(i, j);
      }
    }
    /*
    for(int i = 1; i <= num; i++) {
        cerr << i << " " << name[i] << " " << uni.root(i) << endl;
    }
    */
    for (int i = 1; i <= num; i++) {
      for (int j = 1; j <= num; j++) {
        dist[i][j] = INF;
      }
      dist[i][i] = 0;
    }
    /*
    UnionFind uni2(1000);
    for(int i = 1; i <= N; i++) {
        uni2.merge(mp[before[i]], mp[after[i]] + 200);
        uni2.merge(mp[before[i]] + 200, mp[after[i]]);
        dist[mp[before[i]]][mp[after[i]]] = 1;
    }
    */
    for (int i = 1; i <= N; i++) {
      dist[uni.root(mp[before[i]])][uni.root(mp[after[i]])] = 1;
    }
    for (int i = 1; i <= num; i++) {
      for (int j = 1; j <= num; j++) {
        for (int k = 1; k <= num; k++) {
          chmin(dist[j][k], dist[j][i] + dist[i][k]);
        }
      }
    }
    /*
    for(int i = 1; i <= num; i++) {
        for(int j = 1; j <= num; j++) cerr << dist[i][j] << " ";
        cerr << endl;
    }
    */
    int M;
    cin >> M;
    cout << st.size() << endl;
    while (M--) {
      string in;
      cin >> in;
      string a, b;
      int moji = 0;
      while (in[moji] != '-')
        moji++;
      a = in.substr(0, moji);
      b = in.substr(moji + 1);
      if (st.find(a) == st.end() || st.find(b) == st.end()) {
        cout << "NO" << endl;
        continue;
      }
      a = name[uni.root(mp[a])];
      b = name[uni.root(mp[b])];
      // cerr << a << " " << mp[a] << " " << b << " " << mp[b] << endl;
      /*
      if(!uni2.issame(mp[a], mp[b] + 200)) {
          //cerr << "NOT CONNECTED" << endl;
          cout << "NO" << endl;
          continue;
      }
      */
      // cerr << dist[mp[a]][mp[b]] << endl;
      if (dist[mp[a]][mp[b]] == INF)
        cout << "NO" << endl;
      else if (dist[mp[a]][mp[b]] % 2 == 0)
        cout << "NO" << endl;
      else
        cout << "YES" << endl;
    }
  }
  return 0;
}