Cod sursa(job #2703005)

Utilizator retrogradLucian Bicsi retrograd Data 6 februarie 2021 17:11:19
Problema Nowhere-zero Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.41 kb
#ifdef LOCAL
#include <debug.hpp>
#else
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,tune=native")
#define debug(...)
#endif 

#include <bits/stdc++.h>

using namespace std;
using Point = complex<double>;


int half(Point p) { return p.imag() < 0 || (p.imag() == 0 && p.real() < 0); }

vector<vector<int>> ComputeFaces(vector<Point>& P, auto& graph) {
  int n = graph.size(), piv;
  auto cmp = [&](int a, int b) {
    Point p = P[a] - P[piv], q = P[b] - P[piv];
    return make_pair(half(p), p.imag() * q.real()) < 
      make_pair(half(q), p.real() * q.imag());
  };
  vector<vector<int>> which(n);
  for (int i = 0; i < n; ++i) {
    piv = i; sort(graph[i].begin(), graph[i].end(), cmp);
    which[i].assign(graph[i].size(), -1);
  }
  vector<vector<int>> faces;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < (int)graph[i].size(); ++j) {
      if (which[i][j] != -1) continue;
      vector<int> face;
      int ci = i, cj = j;
      do {
        assert(which[ci][cj] == -1);
        face.push_back(ci);
        int ni = graph[ci][cj], nj;
        piv = ni; nj = lower_bound(graph[ni].begin(),
            graph[ni].end(), ci, cmp) - graph[ni].begin();
        assert(graph[ni][nj] == ci);
        if (++nj == (int)graph[ni].size()) nj = 0;
        which[ci][cj] = faces.size(); ci = ni; cj = nj;
      } while (ci != i);
      assert(cj == j);
      faces.emplace_back(move(face));
    }
  }
  // Can also return `which`, anthough keep in mind that 
  // the graph gets shuffled. 
  return faces;
}

int main() {
  ifstream cin("nowhere-zero.in");
  ofstream cout("nowhere-zero.out");

  int n, m; cin >> n >> m;
  vector<Point> P(n);
  for (int i = 0; i < n; ++i) {
    double x, y; cin >> x >> y;
    P[i] = {x, y};
  }

  vector<vector<int>> graph(n);
  for (int i = 0; i < m; ++i) {
    int a, b; cin >> a >> b; --a; --b;
    graph[a].push_back(b);
    graph[b].push_back(a);
  }
  auto faces = ComputeFaces(P, graph);
  int f = faces.size();
  vector<vector<int>> dual(f);
  vector<int> deg(f, 0);
  vector<tuple<int, int, int>> e2f;
  for (int i = 0; i < f; ++i) {
    int l = faces[i].size();
    for (int j = 0, k = l - 1; j < l; k = j++) {
      e2f.emplace_back(faces[i][k], faces[i][j], i); 
    }
  }
  sort(e2f.begin(), e2f.end());
  auto getf = [&](int a, int b) {
    return get<2>(*lower_bound(e2f.begin(), e2f.end(), make_tuple(a, b, -1)));
  };
  for (int i = 0; i < f; ++i) {
    int l = faces[i].size();
    for (int j = 0, k = l - 1; j < l; k = j++) 
      dual[i].push_back(getf(faces[i][j], faces[i][k])); 
    sort(dual[i].begin(), dual[i].end());
    dual[i].erase(unique(dual[i].begin(), dual[i].end()), dual[i].end());
    deg[i] = dual[i].size();
  }

  vector<int> q;
  for (int i = 0; i < f; ++i)
    if (deg[i] <= 5)
      q.push_back(i);
  for (int i = 0; i < f; ++i) {
    int node = q[i];
    for (auto vec : dual[node]) {
      if (--deg[vec] == 5)
        q.push_back(vec);
    }
  }
  reverse(q.begin(), q.end());
  vector<int> col(f, -1);
  for (auto node : q) {
    int bad = 0;
    for (auto vec : dual[node]) {
      if (col[vec] != -1) 
        bad |= (1 << col[vec]);
    }
    col[node] = 0;
    while (bad & (1 << col[node])) 
      ++col[node];
  }
  
  for (int i = 0; i < n; ++i)
    for (auto j : graph[i]) {
      int df = col[getf(i, j)] - col[getf(j, i)];
      if (df > 0) cout << i + 1 << " " << j + 1 << " " << df << '\n';
    }

  return 0;
}