Cod sursa(job #2703018)

Utilizator retrogradLucian Bicsi retrograd Data 6 februarie 2021 18:16:49
Problema Nowhere-zero Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.26 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 face, origin, nxt, prv; };

vector<Edge> ComputeFaces(vector<Point>& P, vector<pair<int, int>>& E) {
  int n = P.size(), m = E.size();
  for (int i = 0; i < m; ++i) {
    Point p = P[E[i].second] - P[E[i].first];
    if (half(p)) swap(E[i].first, E[i].second);
  }
  vector<int> order(m);
  iota(order.begin(), order.end(), 0);
  sort(order.begin(), order.end(), [&](int a, int b) {
    Point p = P[E[a].second] - P[E[a].first];
    Point q = P[E[b].second] - P[E[b].first];
    return cross(p, q) > 0;
  });
  order.resize(2 * m);
  for (int i = 0; i < m; ++i) {
    order[i + m] = 2 * order[i] + 1;
    order[i] = 2 * order[i];
  }
  vector<int> fst(n, -1), lst(n, -1), nxt(2 * m, -1);
  vector<Edge> ret(2 * m);
  for (auto i : order) {
    int a = (i % 2 ? E[i / 2].second : E[i / 2].first);
    ret[i].origin = a;
    ret[i].face = -1;
    if (fst[a] == -1) fst[a] = i;
    else ret[lst[a]].nxt = i;
    lst[a] = i;
  }
  for (int i = 0; i < n; ++i)
    ret[lst[i]].nxt = fst[i];
  for (int i = 0; i < 2 * m; ++i) {
    if (i % 2 == 0) swap(ret[i].nxt, ret[i + 1].nxt);
    ret[ret[i].nxt].prv = i;
  }

  int f = 0;
  for (int i = 0; i < 2 * m; ++i) {
    if (ret[i].face == -1) {
      for (int j = i; ret[j].face == -1; j = ret[j].nxt)
        ret[j].face = f;
      f++;
    }
  }
  return ret;
}

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);
  vector<pair<int, int>> E;
  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);
    E.emplace_back(a, b);
  }
  auto L = ComputeFaces(P, E);
  int f = 0;
  for (auto x : L) f = max(f, x.face + 1);

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

  return 0;
}