Cod sursa(job #2703025)

Utilizator retrogradLucian Bicsi retrograd Data 6 februarie 2021 18:56:01
Problema Nowhere-zero Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.77 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); }
double cross(Point p, Point q) { return p.real() * q.imag() - p.imag() * q.real(); }

struct Edge { int origin, nxt, face; };

vector<int> ComputeList(vector<Point>& P, vector<array<int, 2>>& E) {
  int n = P.size(), m = E.size();
  vector<int> ord(m);
  iota(ord.begin(), ord.end(), 0);
  sort(ord.begin(), ord.end(), [&](int a, int b) {
    if (E[a][0] != E[b][0]) return E[a][0] < E[b][0];
    Point p = P[E[a][1]] - P[E[a][0]], 
          q = P[E[b][1]] - P[E[b][0]];
    if (half(p) != half(q)) return half(p) < half(q);
    return cross(p, q) > 0;
  });
  int l = 0, r = 0;
  vector<int> nxt(m);
  for (l = 0; l < m; l = r) {
    for (r = l + 1; r < m && E[ord[r]][0] == E[ord[l]][0]; ++r) 
      nxt[ord[r - 1]] = ord[r];
    nxt[ord[r - 1]] = ord[l];
  }
  for (int i = 0; i < m; i += 2) swap(nxt[i], nxt[i ^ 1]);
  return nxt;
}

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<array<int, 2>> E;
  for (int i = 0; i < m; ++i) {
    int a, b; cin >> a >> b; --a; --b;
    E.push_back({a, b});
    E.push_back({b, a});
  }

  m *= 2;
  auto nxt = ComputeList(P, E);
  int f = 0;
  vector<int> which(m, -1);
  for (int i = 0; i < m; ++i) {
    if (which[i] != -1) continue;
    for (int j = i; which[j] == -1; j = nxt[j])
      which[j] = f;
    ++f;
  }

  vector<vector<int>> dual(f);
  for (int i = 0; i < m; ++i) 
    dual[which[i]].push_back(which[i ^ 1]);
  
  vector<int> deg(f, 0);
  for (int i = 0; i < f; ++i) {
    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 < m; ++i) {
    int df = col[which[i]] - col[which[i ^ 1]];
    if (df > 0) 
      cout << E[i][0] + 1 << " " << E[i][1] + 1 << " " << df << '\n';
  }

  return 0;
}