Cod sursa(job #968451)

Utilizator pauldbPaul-Dan Baltescu pauldb Data 2 iulie 2013 03:53:23
Problema Nowhere-zero Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.82 kb
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

const int MAX_N = 100010;
const int MAX_M = 300010;
const int MAX_F = 200010;
const int NUM_COLORS = 6;

int n, m, num_faces;
pair<double, double> coord[MAX_N];
pair<int, int> edges[MAX_M], edge_faces[MAX_M];
vector<pair<int, int>> graph[MAX_N];
unordered_set<int> dual_graph[MAX_F];
unordered_map<int, int> index[MAX_N];
vector<bool> visited[MAX_N];
int deg[MAX_F], selected[MAX_F];
vector<int> coloring;

void ReadData() {
  scanf("%d %d ", &n, &m);
  for (int i = 1; i <= n; ++i) {
    scanf("%lf %lf ", &coord[i].first, &coord[i].second);
  }

  for (int i = 1; i <= m; ++i) {
    int x, y;
    scanf("%d %d ", &x, &y);
    graph[x].push_back(make_pair(i, y));
    graph[y].push_back(make_pair(i, x));
  }
}

void ConstructDualGraph() {
  for (int i = 1; i <= n; ++i) {
    auto o = coord[i];
    sort(graph[i].begin(), graph[i].end(),
        [&o](const pair<int, int>& c1, const pair<int, int>& c2) {
          int v1 = c1.second;
          int v2 = c2.second;
          return atan2(coord[v1].first - o.first, coord[v1].second - o.second) <
                 atan2(coord[v2].first - o.first, coord[v2].second - o.second);
        });
  }

  for (int i = 1; i <= n; ++i) {
    visited[i].resize(graph[i].size());
    for (size_t j = 0; j < graph[i].size(); ++j) {
      index[i][graph[i][j].second] = j;
    }
  }

  for (int i = 1; i <= n; ++i) {
    for (size_t j = 0; j < graph[i].size(); ++j) {
      if (visited[i][j]) {
        continue;
      }

      ++num_faces;
      int node = i, pos = j;
      do {
        visited[node][pos] = true;
        int edge = graph[node][pos].first;
        int next_node = graph[node][pos].second;
        if (edge_faces[edge].first == 0) {
          edge_faces[edge].first = num_faces;
          edges[edge] = make_pair(node, next_node);
        } else {
          edge_faces[edge].second = num_faces;
        }
        pos = (index[next_node][node] + 1) % graph[next_node].size();
        node = next_node;
      } while (node != i);
    }
  }

  for (int i = 1; i <= m; ++i) {
    dual_graph[edge_faces[i].first].insert(edge_faces[i].second);
    dual_graph[edge_faces[i].second].insert(edge_faces[i].first);
  }
}

void FindDualGraphColoring() {
  vector<int> ordering;
  set<pair<int, int>> candidates;
  for (int i = 1; i <= num_faces; ++i) {
    deg[i] = dual_graph[i].size();
    candidates.insert(make_pair(deg[i], i));
  }

  while (!candidates.empty()) {
    int node = candidates.begin()->second;
    candidates.erase(candidates.begin());
    if (selected[node]) {
      continue;
    }

    selected[node] = true;
    ordering.push_back(node);
    for (int v: dual_graph[node]) {
      if (!selected[v]) {
        --deg[v];
        candidates.insert(make_pair(deg[v], v));
      }
    }
  }

  reverse(ordering.begin(), ordering.end());

  coloring.resize(num_faces + 1);
  vector<int> used_colors(NUM_COLORS + 1);
  for (int node: ordering) {
    for (int v: dual_graph[node]) {
      used_colors[coloring[v]] = node;
    }

    bool found_color = false;
    for (int i = 1; i <= NUM_COLORS; ++i) {
      if (used_colors[i] != node) {
        coloring[node] = i;
        found_color = true;
        break;
      }
    }
    assert(found_color);
  }
}

void PrintSolution() {
  for (int i = 1; i <= m; ++i) {
    int diff = coloring[edge_faces[i].first] - coloring[edge_faces[i].second];
    if (diff < 0) {
      printf("%d %d %d\n", edges[i].first, edges[i].second, -diff);
    } else {
      printf("%d %d %d\n", edges[i].second, edges[i].first, diff);
    }
  }
}

int main() {
  freopen("nowhere-zero.in", "r", stdin);
  freopen("nowhere-zero.out", "w", stdout);

  ReadData();
  ConstructDualGraph();
  FindDualGraphColoring();
  PrintSolution();

  return 0;
}