#include <bits/stdc++.h>
using namespace std;
const int N = 205;
const int V = 2 * N + 5;
const int E = 1000500;
const int INF = (int)1e9;
struct Edge {
  int to, flow, cap, ref;
  Edge() : to(), flow(), cap(), ref() {}
  Edge(int _to, int _cap, int _ref) : to(_to), flow(), cap(_cap), ref(_ref) {}
};
int go[V];
Edge e[E];
int vcnt, ecnt;
int fake_gs, fake_gt;
int gs, gt;
void add_edge(int a, int b, int cap) {
  e[ecnt] = Edge(b, cap, go[a]);
  go[a] = ecnt++;
  e[ecnt] = Edge(a, 0, go[b]);
  go[b] = ecnt++;
}
void modify_edge(int a, int b, int lower_cap, int upper_cap) {
  add_edge(gs, b, lower_cap);
  add_edge(a, gt, lower_cap);
  add_edge(a, b, upper_cap - lower_cap);
}
int cur_go[V];
int dist[V];
int q[V];
int ql, qr;
bool bfs() {
  copy(go, go + vcnt, cur_go);
  fill(dist, dist + vcnt, INF);
  dist[gs] = 0;
  ql = qr = 0;
  q[qr++] = gs;
  while (ql < qr) {
    int v = q[ql++];
    for (int i = go[v]; i != -1; i = e[i].ref) {
      if (e[i].flow == e[i].cap) continue;
      int to = e[i].to;
      if (dist[to] == INF) {
        dist[to] = dist[v] + 1;
        q[qr++] = to;
      }
    }
  }
  return dist[gt] != INF;
}
int dfs(int v, int flow) {
  if (v == gt || flow == 0) return flow;
  for (int& i = cur_go[v]; i != -1; i = e[i].ref) {
    int to = e[i].to;
    if (dist[to] != dist[v] + 1) continue;
    int ret = dfs(to, min(flow, e[i].cap - e[i].flow));
    if (ret > 0) {
      e[i].flow += ret;
      e[i ^ 1].flow -= ret;
      return ret;
    }
  }
  return 0;
}
void find_flow() {
  while (bfs())
    while (dfs(gs, INF) > 0) {
    }
}
int n, m, k, t;
int edge_index[N][N];
bool has_edge[N][N];
int left_deg[N], right_deg[N];
int color[N * N];
void build_network(int cur_t) {
  fake_gs = n + m;
  fake_gt = fake_gs + 1;
  gs = fake_gt + 1;
  gt = gs + 1;
  vcnt = gt + 1;
  ecnt = 0;
  fill(go, go + vcnt, -1);
  for (int i = 0; i < n; i++)
    modify_edge(fake_gs, i, left_deg[i] / cur_t,
                (left_deg[i] + cur_t - 1) / cur_t);
  for (int i = 0; i < m; i++)
    modify_edge(n + i, fake_gt, right_deg[i] / cur_t,
                (right_deg[i] + cur_t - 1) / cur_t);
  add_edge(fake_gt, fake_gs, INF);
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
      if (has_edge[i][j]) add_edge(i, n + j, 1);
}
void process_network(int col) {
  for (int i = 0; i < n; i++)
    for (int j = go[i]; j != -1; j = e[j].ref) {
      if (e[j].to >= n + m) continue;
      int to = e[j].to - n;
      if (e[j].flow == 1) {
        has_edge[i][to] = false;
        left_deg[i]--;
        right_deg[to]--;
        color[edge_index[i][to]] = col;
      }
    }
}
void solve() {
  memset(color, -1, sizeof(color));
  scanf("%d%d%d%d", &n, &m, &k, &t);
  for (int i = 0; i < k; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    a--;
    b--;
    has_edge[a][b] = true;
    edge_index[a][b] = i;
    left_deg[a]++;
    right_deg[b]++;
  }
  int ans = 0;
  for (int i = 0; i < n; i++)
    if (left_deg[i] % t != 0) ans++;
  for (int i = 0; i < m; i++)
    if (right_deg[i] % t != 0) ans++;
  int cur_t = t;
  for (int i = 0; i < t; i++) {
    build_network(cur_t);
    cur_t--;
    find_flow();
    process_network(i);
  }
  printf("%d\n", ans);
  for (int i = 0; i < k; i++) printf("%d ", color[i] + 1);
}
int main() {
  solve();
  0;
  return 0;
}
