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

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct Dice {
  int face[6];
  Dice() { MEMSET(face, 0); }
  // +Z
  int Top() const { return face[0]; }
  int &Top() { return face[0]; }
  // -Z
  int Bottom() const { return face[1]; }
  int &Bottom() { return face[1]; }
  // +X
  int Right() const { return face[2]; }
  int &Right() { return face[2]; }
  // -X
  int Left() const { return face[3]; }
  int &Left() { return face[3]; }
  // +Y
  int Front() const { return face[4]; }
  int &Front() { return face[4]; }
  // -Y
  int Back() const { return face[5]; }
  int &Back() { return face[5]; }

  Dice Rotate(int cnt, int dir) const {
    if (cnt == 0) {
      return *this;
    }
    if (cnt < 0) {
      cnt = cnt % 4 + 4;
    } else {
      cnt %= 4;
    }
    Dice ret;
    if (dir == 0) {
      // +X rotate(Y axis rotate)
      ret.face[0] = face[3];
      ret.face[1] = face[2];
      ret.face[2] = face[0];
      ret.face[3] = face[1];
      ret.face[4] = face[4];
      ret.face[5] = face[5];
    } else if (dir == 1) {
      // +Y rotate(X axis rotate)
      ret.face[0] = face[4];
      ret.face[1] = face[5];
      ret.face[2] = face[2];
      ret.face[3] = face[3];
      ret.face[4] = face[1];
      ret.face[5] = face[0];
    } else if (dir == 2) {
      // Z rotate(Z axis rotate)
      ret.face[0] = face[0];
      ret.face[1] = face[1];
      ret.face[2] = face[4];
      ret.face[3] = face[5];
      ret.face[4] = face[3];
      ret.face[5] = face[2];
    } else {
      assert(false);
    }
    return ret.Rotate(cnt - 1, dir);
  }
  vector<Dice> AllRotate() const {
    vector<Dice> ret;
    Dice temp = *this;
    REP(i, 6) {
      REP(j, 4) {
        ret.push_back(temp);
        temp = temp.Rotate(1, 2);
      }
      temp = temp.Rotate(1, i & 1);
    }
    return ret;
  }
  bool operator==(const Dice &rhs) const {
    REP(i, 6) {
      if (face[i] != rhs.face[i]) {
        return false;
      }
    }
    return true;
  }
  bool operator<(const Dice &rhs) const {
    REP(i, 6) {
      if (face[i] != rhs.face[i]) {
        return face[i] < rhs.face[i];
      }
    }
    return false;
  }
};

typedef int Weight;
struct Edge {
  int src;
  int dest;
  Weight weight;
  Edge(int src, int dest, Weight weight)
      : src(src), dest(dest), weight(weight) {
    ;
  }
  bool operator<(const Edge &rhs) const {
    if (weight != rhs.weight) {
      return weight > rhs.weight;
    }
    if (src != rhs.src) {
      return src < rhs.src;
    }
    return dest < rhs.dest;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void PrintMatrix(const Matrix &matrix) {
  for (int y = 0; y < (int)matrix.size(); y++) {
    for (int x = 0; x < (int)matrix[y].size(); x++) {
      printf("%d ", matrix[y][x]);
    }
    puts("");
  }
}

int capacity[20][20];
Weight augment(const Graph &g, const vector<int> &level, vector<bool> &finished,
               int from, int t, Weight cur) {
  if (from == t || cur == 0) {
    return cur;
  }
  if (finished[from]) {
    return 0;
  }
  for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
    int to = it->dest;
    if (level[to] <= level[from]) {
      continue;
    }
    Weight f = augment(g, level, finished, to, t, min(cur, capacity[from][to]));
    if (f > 0) {
      capacity[from][to] -= f;
      capacity[to][from] += f;
      return f;
    }
  }
  finished[from] = true;
  return 0;
}

Weight MaxFlow(const Graph &g, int s, int t) {
  int n = g.size();
  int ans = 0;
  while (true) {
    vector<int> level(n, -1);
    level[s] = 0;
    queue<int> que;
    que.push(s);
    for (int d = n; !que.empty() && level[que.front()] < d;) {
      int from = que.front();
      que.pop();
      if (from == t) {
        d = level[from];
      }
      for (Edges::const_iterator it = g[from].begin(); it != g[from].end();
           it++) {
        int to = it->dest;
        if (capacity[from][to] > 0 && level[to] == -1) {
          que.push(to);
          level[to] = level[from] + 1;
        }
      }
    }
    vector<bool> finished(n);
    bool end = true;
    while (true) {
      Weight f = augment(g, level, finished, s, t, 2000000000LL);
      if (f == 0) {
        break;
      }
      ans += f;
      end = false;
    }
    if (end) {
      break;
    }
  }
  return ans;
}

void AddEdge(Graph &g, int from, int to, Weight capacity) {
  g[from].push_back(Edge(from, to, capacity));
  g[to].push_back(Edge(to, from, 0));
}

int IN(int x) { return x * 2; }
int OUT(int x) { return x * 2 + 1; }
int SOURCE() { return 12; }
int DEST() { return 13; }
int SIZE() { return 14; }
const int INF = 1e+9;

int wants[6];
int p, q;
string ans;
char str[100000];
Graph g;

void MakeGraph() {
  g = Graph(SIZE());
  REP(i, 6) {
    AddEdge(g, SOURCE(), IN(i), 0);
    AddEdge(g, OUT(i), DEST(), 0);
    REP(next, 6) {
      if (i == next || i == (next ^ 1)) {
        continue;
      }
      AddEdge(g, IN(i), OUT(next), 0);
    }
  }
}
bool ok(const Dice &now, const Dice &goal) {
  REP(end, 6) {
    int candidate = 0;
    MEMSET(capacity, 0);
    REP(i, 6) {
      int rest = goal.face[i] - now.face[i];
      // cout << "Rest: " << rest << endl;
      if (rest < 0) {
        return false;
      }
      capacity[SOURCE()][IN(i)] = rest + (i == 1 ? 1 : 0) - (i == end ? 1 : 0);
      capacity[OUT(i)][DEST()] = rest;
      candidate += rest;
      REP(next, 6) {
        if (i == next || i == (next ^ 1)) {
          continue;
        }
        capacity[IN(i)][OUT(next)] = INF;
      }
    }
    if (MaxFlow(g, SOURCE(), DEST()) == candidate) {
      return true;
    }
    // cout << "hoge" << endl;
  }
  return false;
}

int main() {
  MakeGraph();
  while (true) {
    ans = "~";
    int n = 0;
    REP(i, 6) {
      scanf("%d", &wants[i]);
      n += wants[i];
    }
    if (n == 0) {
      break;
    }
    scanf("%d %d", &p, &q);
    sort(wants, wants + 6);
    Dice dice;
    vector<Dice> goals;
    do {
      Dice goal;
      memcpy(goal.face, wants, sizeof(wants));
      if (!ok(dice, goal)) {
        continue;
      }
      goals.push_back(goal);
    } while (next_permutation(wants, wants + 6));
    if (goals.size() == 0) {
      puts("impossible");
      continue;
    }

    REP(i, n) {
      random_shuffle(goals.begin(), goals.end());
      const char dchar[4] = {'E', 'N', 'S', 'W'};
      const int rotate[4] = {0, 1, 1, 0};
      const int r_cnt[4] = {1, 1, -1, -1};
      REP(dir, 4) {
        Dice ndice = dice.Rotate(r_cnt[dir], rotate[dir]);
        ndice.face[1]++;
        REP(j, goals.size()) {
          if (ok(ndice, goals[j].Rotate(r_cnt[dir], rotate[dir]))) {
            dice = ndice;
            // cout << j << " " << goals.size() << endl;
            goals.erase(goals.begin(), goals.begin() + j);
            FORIT(it, goals) { *it = it->Rotate(r_cnt[dir], rotate[dir]); }
            str[i] = dchar[dir];
            goto next;
          }
        }
        assert(dir != 3);
      }
    next:;
    }
    ans = str;
    printf("%s\\n", ans.substr(p - 1, q - p + 1).c_str());
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct Dice {
  int face[6];
  Dice() { MEMSET(face, 0); }
  // +Z
  int Top() const { return face[0]; }
  int &Top() { return face[0]; }
  // -Z
  int Bottom() const { return face[1]; }
  int &Bottom() { return face[1]; }
  // +X
  int Right() const { return face[2]; }
  int &Right() { return face[2]; }
  // -X
  int Left() const { return face[3]; }
  int &Left() { return face[3]; }
  // +Y
  int Front() const { return face[4]; }
  int &Front() { return face[4]; }
  // -Y
  int Back() const { return face[5]; }
  int &Back() { return face[5]; }

  Dice Rotate(int cnt, int dir) const {
    if (cnt == 0) {
      return *this;
    }
    if (cnt < 0) {
      cnt = cnt % 4 + 4;
    } else {
      cnt %= 4;
    }
    Dice ret;
    if (dir == 0) {
      // +X rotate(Y axis rotate)
      ret.face[0] = face[3];
      ret.face[1] = face[2];
      ret.face[2] = face[0];
      ret.face[3] = face[1];
      ret.face[4] = face[4];
      ret.face[5] = face[5];
    } else if (dir == 1) {
      // +Y rotate(X axis rotate)
      ret.face[0] = face[4];
      ret.face[1] = face[5];
      ret.face[2] = face[2];
      ret.face[3] = face[3];
      ret.face[4] = face[1];
      ret.face[5] = face[0];
    } else if (dir == 2) {
      // Z rotate(Z axis rotate)
      ret.face[0] = face[0];
      ret.face[1] = face[1];
      ret.face[2] = face[4];
      ret.face[3] = face[5];
      ret.face[4] = face[3];
      ret.face[5] = face[2];
    } else {
      assert(false);
    }
    return ret.Rotate(cnt - 1, dir);
  }
  vector<Dice> AllRotate() const {
    vector<Dice> ret;
    Dice temp = *this;
    REP(i, 6) {
      REP(j, 4) {
        ret.push_back(temp);
        temp = temp.Rotate(1, 2);
      }
      temp = temp.Rotate(1, i & 1);
    }
    return ret;
  }
  bool operator==(const Dice &rhs) const {
    REP(i, 6) {
      if (face[i] != rhs.face[i]) {
        return false;
      }
    }
    return true;
  }
  bool operator<(const Dice &rhs) const {
    REP(i, 6) {
      if (face[i] != rhs.face[i]) {
        return face[i] < rhs.face[i];
      }
    }
    return false;
  }
};

typedef int Weight;
struct Edge {
  int src;
  int dest;
  Weight weight;
  Edge(int src, int dest, Weight weight)
      : src(src), dest(dest), weight(weight) {
    ;
  }
  bool operator<(const Edge &rhs) const {
    if (weight != rhs.weight) {
      return weight > rhs.weight;
    }
    if (src != rhs.src) {
      return src < rhs.src;
    }
    return dest < rhs.dest;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void PrintMatrix(const Matrix &matrix) {
  for (int y = 0; y < (int)matrix.size(); y++) {
    for (int x = 0; x < (int)matrix[y].size(); x++) {
      printf("%d ", matrix[y][x]);
    }
    puts("");
  }
}

int capacity[20][20];
Weight augment(const Graph &g, const vector<int> &level, vector<bool> &finished,
               int from, int t, Weight cur) {
  if (from == t || cur == 0) {
    return cur;
  }
  if (finished[from]) {
    return 0;
  }
  for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
    int to = it->dest;
    if (level[to] <= level[from]) {
      continue;
    }
    Weight f = augment(g, level, finished, to, t, min(cur, capacity[from][to]));
    if (f > 0) {
      capacity[from][to] -= f;
      capacity[to][from] += f;
      return f;
    }
  }
  finished[from] = true;
  return 0;
}

Weight MaxFlow(const Graph &g, int s, int t) {
  int n = g.size();
  int ans = 0;
  while (true) {
    vector<int> level(n, -1);
    level[s] = 0;
    queue<int> que;
    que.push(s);
    for (int d = n; !que.empty() && level[que.front()] < d;) {
      int from = que.front();
      que.pop();
      if (from == t) {
        d = level[from];
      }
      for (Edges::const_iterator it = g[from].begin(); it != g[from].end();
           it++) {
        int to = it->dest;
        if (capacity[from][to] > 0 && level[to] == -1) {
          que.push(to);
          level[to] = level[from] + 1;
        }
      }
    }
    vector<bool> finished(n);
    bool end = true;
    while (true) {
      Weight f = augment(g, level, finished, s, t, 2000000000LL);
      if (f == 0) {
        break;
      }
      ans += f;
      end = false;
    }
    if (end) {
      break;
    }
  }
  return ans;
}

void AddEdge(Graph &g, int from, int to, Weight capacity) {
  g[from].push_back(Edge(from, to, capacity));
  g[to].push_back(Edge(to, from, 0));
}

int IN(int x) { return x * 2; }
int OUT(int x) { return x * 2 + 1; }
int SOURCE() { return 12; }
int DEST() { return 13; }
int SIZE() { return 14; }
const int INF = 1e+9;

int wants[6];
int p, q;
string ans;
char str[100000];
Graph g;

void MakeGraph() {
  g = Graph(SIZE());
  REP(i, 6) {
    AddEdge(g, SOURCE(), IN(i), 0);
    AddEdge(g, OUT(i), DEST(), 0);
    REP(next, 6) {
      if (i == next || i == (next ^ 1)) {
        continue;
      }
      AddEdge(g, IN(i), OUT(next), 0);
    }
  }
}
bool ok(const Dice &now) {
  REP(end, 6) {
    int candidate = 0;
    MEMSET(capacity, 0);
    REP(i, 6) {
      int rest = now.face[i];
      // cout << "Rest: " << rest << endl;
      if (rest < 0) {
        return false;
      }
      capacity[SOURCE()][IN(i)] = rest + (i == 1 ? 1 : 0) - (i == end ? 1 : 0);
      capacity[OUT(i)][DEST()] = rest;
      candidate += rest;
      REP(next, 6) {
        if (i == next || i == (next ^ 1)) {
          continue;
        }
        capacity[IN(i)][OUT(next)] = INF;
      }
    }
    if (MaxFlow(g, SOURCE(), DEST()) == candidate) {
      return true;
    }
    // cout << "hoge" << endl;
  }
  return false;
}

int main() {
  MakeGraph();
  while (true) {
    ans = "~";
    int n = 0;
    REP(i, 6) {
      scanf("%d", &wants[i]);
      n += wants[i];
    }
    if (n == 0) {
      break;
    }
    scanf("%d %d", &p, &q);
    sort(wants, wants + 6);
    do {
      Dice goal;
      memcpy(goal.face, wants, sizeof(wants));
      if (!ok(goal)) {
        continue;
      }
      const char dchar[4] = {'E', 'N', 'S', 'W'};
      const int rotate[4] = {0, 1, 1, 0};
      const int r_cnt[4] = {1, 1, -1, -1};
      REP(i, n) {
        // REP(j, 6) {
        //   cout << goal.face[j] << " ";
        // }
        // cout << endl;
        REP(dir, 4) {
          Dice ngoal = goal.Rotate(r_cnt[dir], rotate[dir]);
          ngoal.face[1]--;
          // cout << dir << endl;
          if (ok(ngoal)) {
            goal = ngoal;
            str[i] = dchar[dir];
            break;
          }
          assert(dir != 3);
        }
      }
      ans = min(ans, (string)str);
    } while (next_permutation(wants, wants + 6));
    if (ans == "~") {
      puts("impossible");
    } else {
      printf("%s\\n", ans.substr(p - 1, q - p + 1).c_str());
      ;
    }
  }
}