#include <bits/stdc++.h>
inline void bye() { puts("IMPOSSIBLE"), exit(0); }
int lT, rT;
int n, m;
int L[100050], R[100050];
struct edge {
  int to, nxt;
} E[200050];
int H[100050], tot;
void add_edge(int a, int b) {
  E[++tot] = (edge){b, H[a]}, H[a] = tot;
  E[++tot] = (edge){a, H[b]}, H[b] = tot;
}
int cl1, cr1, cl2, cr2;
int vis[100050];
std::vector<int> zero, one;
void dfs(int now, int flg = 0) {
  vis[now] = flg;
  (flg ? one : zero).push_back(now);
  if (flg) {
    cl2 = std::max(cl2, L[now]);
    cr2 = std::min(cr2, R[now]);
  } else {
    cl1 = std::max(cl1, L[now]);
    cr1 = std::min(cr1, R[now]);
  }
  for (int i = H[now]; i; i = E[i].nxt) {
    if (~vis[E[i].to]) {
      if (!(vis[E[i].to] ^ flg)) bye();
    } else
      dfs(E[i].to, !flg);
  }
}
struct oper {
  int L1, R1, T, flg;
} O[800050];
int optot;
int ranL[800050], ranR[800050];
int tmp[800050], tmptot;
struct SegmentTree {
  struct node {
    int mxval, tag, mxpos;
  } T[10000000];
  void puttag(int o, int v) { T[o].tag += v, T[o].mxval += v; }
  void pushdown(int o) {
    puttag(o << 1, T[o].tag), puttag(o << 1 | 1, T[o].tag);
    T[o].tag = 0;
  }
  void update(int o) {
    if (T[o << 1].mxval > T[o << 1 | 1].mxval)
      T[o].mxval = T[o << 1].mxval, T[o].mxpos = T[o << 1].mxpos;
    else
      T[o].mxval = T[o << 1 | 1].mxval, T[o].mxpos = T[o << 1 | 1].mxpos;
  }
  void modify(int o, int l, int r, int L, int R, int t) {
    if (ranL[l] > R || ranR[r] < L) return;
    if (L <= ranL[l] && ranR[r] <= R)
      puttag(o, t);
    else {
      pushdown(o);
      int mdl = (l + r) >> 1;
      modify(o << 1, l, mdl, L, R, t);
      modify(o << 1 | 1, mdl + 1, r, L, R, t);
      update(o);
    }
  }
  std::pair<int, int> query(int o, int l, int r, int L, int R) {
    if (ranL[l] > R || ranR[r] < L) return std::make_pair(-1000000000, 0);
    if (l == r || (L <= ranL[l] && ranR[r] <= R))
      return std::make_pair(T[o].mxval, T[o].mxpos);
    pushdown(o);
    int mdl = (l + r) >> 1;
    return std::max(query(o << 1, l, mdl, L, R),
                    query(o << 1 | 1, mdl + 1, r, L, R));
  }
  void init(int o, int l, int r) {
    T[o].mxpos = l;
    if (l == r)
      return;
    else {
      int mdl = (l + r) >> 1;
      init(o << 1, l, mdl);
      init(o << 1 | 1, mdl + 1, r);
    }
  }
} T;
int ctot, finalL, finalR;
int col[100050];
bool touch;
int main() {
  scanf("%d%d", &lT, &rT);
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%d%d", &L[i], &R[i]);
  for (int i = 1, x, y; i <= m; i++) scanf("%d%d", &x, &y), add_edge(x, y);
  memset(vis, 0xff, sizeof(vis));
  tmp[++tmptot] = 0;
  tmp[++tmptot] = 1000000001;
  for (int i = 1; i <= n; i++)
    if (!~vis[i]) {
      cl1 = 0, cr1 = 1000000000, cl2 = 0, cr2 = 1000000000;
      dfs(i);
      if (cl1 > cr1 || cl2 > cr2) bye();
      O[++optot] = (oper){cl1, cr1, cl2, 1};
      O[++optot] = (oper){cl1, cr1, cr2 + 1, -1};
      O[++optot] = (oper){cl2, cr2, cl1, 1};
      O[++optot] = (oper){cl2, cr2, cr1 + 1, -1};
      if (std::max(cl1, cl2) <= std::min(cr1, cr2)) {
        O[++optot] = (oper){std::max(cl1, cl2), std::min(cr1, cr2),
                            std::max(cl1, cl2), -1};
        O[++optot] = (oper){std::max(cl1, cl2), std::min(cr1, cr2),
                            std::min(cr1, cr2) + 1, 1};
      }
      tmp[++tmptot] = cl1;
      tmp[++tmptot] = cl2;
      tmp[++tmptot] = cr1 + 1;
      tmp[++tmptot] = cr2 + 1;
      ctot++;
    }
  std::sort(tmp + 1, tmp + tmptot + 1);
  tmptot = std::unique(tmp + 1, tmp + tmptot + 1) - tmp - 1;
  for (int i = 1; i < tmptot; i++) ranL[i] = tmp[i], ranR[i] = tmp[i + 1] - 1;
  tmptot--;
  T.init(1, 1, tmptot);
  std::sort(O + 1, O + optot + 1,
            [](const oper &A, const oper &B) { return A.T < B.T; });
  for (int L = 1, R; L <= optot; L = R + 1) {
    R = L;
    while (R < optot && O[R + 1].T == O[R].T) R++;
    for (int i = L; i <= R; i++) {
      T.modify(1, 1, tmptot, O[i].L1, O[i].R1, O[i].flg);
    }
    if (R == optot) break;
    std::pair<int, int> getv =
        T.query(1, 1, tmptot, lT - O[R + 1].T + 1, rT - O[L].T);
    if (getv.first == ctot) {
      assert(std::max(O[L].T + ranL[getv.second], lT) <=
             std::min(O[R + 1].T + ranR[getv.second], rT));
      int ans = std::max(O[L].T + ranL[getv.second], lT);
      if (O[L].T + ranR[getv.second] >= ans) {
        finalL = ans - O[L].T;
        finalR = O[L].T;
      } else {
        finalL = ranR[getv.second];
        finalR = ans - ranR[getv.second];
      }
      touch = true;
      break;
    }
  }
  if (!touch) bye();
  puts("POSSIBLE");
  printf("%d %d\n", finalL, finalR);
  memset(vis, 0xff, sizeof(vis));
  for (int i = 1; i <= n; i++)
    if (!~vis[i]) {
      zero.clear(), one.clear();
      cl1 = 0, cr1 = 1000000000, cl2 = 0, cr2 = 1000000000;
      dfs(i, 0);
      assert(
          (cl1 <= finalL && finalL <= cr1 && cl2 <= finalR && finalR <= cr2) ||
          (cl1 <= finalR && finalR <= cr1 && cl2 <= finalL && finalL <= cr2));
      if (cl1 <= finalL && finalL <= cr1 && cl2 <= finalR && finalR <= cr2) {
        for (int j : zero) col[j] = 1;
        for (int j : one) col[j] = 2;
      } else {
        for (int j : zero) col[j] = 2;
        for (int j : one) col[j] = 1;
      }
    }
  for (int i = 1; i <= n; i++) printf("%d", col[i]);
}
