#include <bits/stdc++.h>
using std::pair;
using std::vector;
using Node = size_t;
using Edge = pair<Node, Node>;
using EdgeList = vector<Edge>;
using Color = size_t;
using Coloring = vector<Color>;
pair<EdgeList, size_t> ReadInput(std::istream& in_stream = std::cin);
void WriteAnswer(const Coloring& coloring,
                 std::ostream& out_stream = std::cout);
Coloring ColorEdges(const EdgeList& edges, const size_t nodes);
int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);
  auto input = ReadInput();
  auto coloring = ColorEdges(input.first, input.second);
  WriteAnswer(coloring);
  return 0;
}
using EdgeNumber = size_t;
using NodeColoring = vector<pair<pair<Node, EdgeNumber>, bool>>;
Color GetMinColor(const NodeColoring& fst, const NodeColoring& snd);
bool SwapColors(const NodeColoring& fst, const NodeColoring& snd,
                pair<Color, Color>* result);
void SwapColors(Node a, Color fst, Color snd,
                vector<NodeColoring>* node_by_color);
Coloring ColorEdges(const EdgeList& edges, const size_t nodes) {
  Coloring coloring(edges.size());
  vector<NodeColoring> node_by_color(nodes);
  auto resize_node = [&node_by_color](Node node, size_t size) {
    auto current_size = node_by_color[node].size();
    size = std::max(size, current_size);
    node_by_color[node].resize(size);
  };
  auto color_edge = [&node_by_color, &resize_node](Edge edge, EdgeNumber num,
                                                   Color color) {
    Node a = edge.first, b = edge.second;
    resize_node(a, color + 1);
    resize_node(b, color + 1);
    assert(node_by_color[a][color].second == false &&
           node_by_color[b][color].second == false);
    node_by_color[a][color] = {{b, num}, true};
    node_by_color[b][color] = {{a, num}, true};
  };
  for (EdgeNumber edge_num = 0; edge_num < edges.size(); ++edge_num) {
    const Edge& edge = edges[edge_num];
    Node a = edge.first, b = edge.second;
    pair<Color, Color> swapable;
    Color color;
    if (SwapColors(node_by_color[a], node_by_color[b], &swapable)) {
      SwapColors(a, swapable.first, swapable.second, &node_by_color);
      color = swapable.first;
    } else {
      color = GetMinColor(node_by_color[a], node_by_color[b]);
    }
    color_edge(edge, edge_num, color);
  }
  for (Node node = 0; node < nodes; ++node) {
    for (size_t color = 0; color < node_by_color[node].size(); ++color) {
      auto& edge = node_by_color[node][color];
      if (edge.second) {
        auto edge_number = edge.first.second;
        coloring[edge_number] = color;
      }
    }
  }
  return coloring;
}
void SwapColors(Node node, Color fst, Color snd,
                vector<NodeColoring>* node_by_color) {
  auto free_way = [&node_by_color](Node node, Color color) {
    return node_by_color->at(node).size() <= color ||
           node_by_color->at(node)[color].second == false;
  };
  auto resize_node = [&node_by_color](Node node, size_t size) {
    auto current_size = node_by_color->at(node).size();
    size = std::max(size, current_size);
    node_by_color->at(node).resize(size);
  };
  resize_node(node, std::max(fst, snd) + 1);
  if (!free_way(node, fst)) {
    SwapColors(node_by_color->at(node)[fst].first.first, snd, fst,
               node_by_color);
  }
  std::swap(node_by_color->at(node)[fst], node_by_color->at(node)[snd]);
}
bool SwapColors(const NodeColoring& fst, const NodeColoring& snd,
                pair<Color, Color>* result) {
  Color fst_color, snd_color;
  auto free_color = [](Color color, const NodeColoring& smth) {
    return color >= smth.size() || (!smth[color].second);
  };
  auto busy_color = [](Color color, const NodeColoring& smth) {
    return color < smth.size() && smth[color].second;
  };
  for (fst_color = 0; fst_color < fst.size(); ++fst_color) {
    if (busy_color(fst_color, fst) && free_color(fst_color, snd)) {
      break;
    }
  }
  for (snd_color = 0; snd_color < snd.size(); ++snd_color) {
    if (busy_color(snd_color, snd) && free_color(snd_color, fst)) {
      break;
    }
  }
  if (fst_color == fst.size() || snd_color == snd.size()) {
    return false;
  }
  if (result != nullptr) {
    *result = {fst_color, snd_color};
  }
  return true;
}
Color GetMinColor(const NodeColoring& fst, const NodeColoring& snd) {
  Color color;
  for (color = 0; color < fst.size() || color < snd.size(); ++color) {
    bool flag = 1;
    if (color < fst.size()) {
      flag = flag && (!fst[color].second);
    }
    if (color < snd.size()) {
      flag = flag && (!snd[color].second);
    }
    if (flag) {
      break;
    }
  }
  return color;
}
pair<EdgeList, size_t> ReadInput(std::istream& in_stream) {
  size_t nodes_a, nodes_b, edges_size;
  in_stream >> nodes_a >> nodes_b >> edges_size;
  EdgeList edges(edges_size);
  for (auto& edge : edges) {
    in_stream >> edge.first >> edge.second;
    --edge.first, --edge.second;
    edge.second += nodes_a;
  }
  return {edges, nodes_a + nodes_b};
}
void WriteAnswer(const Coloring& coloring, std::ostream& out_stream) {
  if (coloring.empty()) {
    out_stream << 0;
    return;
  }
  auto max_color = *std::max_element(coloring.begin(), coloring.end());
  out_stream << max_color + 1 << std::endl;
  for (auto color : coloring) {
    out_stream << color + 1 << ' ';
  }
}
