Cod sursa(job #3348152)

Utilizator dummy-accdummy acc dummy-acc Data 20 martie 2026 00:29:40
Problema Nowhere-zero Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 7.82 kb
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,popcnt")
#include <bits/stdc++.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

static char *rp;

static inline int read_int() {
    while (*rp <= ' ') rp++;
    bool neg = *rp == '-'; rp += neg;
    unsigned x = 0;
    while ((unsigned)(*rp - '0') < 10u) x = x * 10 + (*rp++ - '0');
    return neg ? -(int)x : (int)x;
}

static inline long long read_fixed() {
    while (*rp <= ' ') rp++;
    bool neg = *rp == '-'; rp += neg;
    long long ip = 0;
    while ((unsigned)(*rp - '0') < 10u) ip = ip * 10 + (*rp++ - '0');
    long long fr = 0; int fd = 0;
    if (*rp == '.') {
        rp++;
        while ((unsigned)(*rp - '0') < 10u) { fr = fr * 10 + (*rp++ - '0'); fd++; }
    }
    while (fd < 6) { fr *= 10; fd++; }
    long long r = ip * 1000000LL + fr;
    return neg ? -r : r;
}


static char obuf[1 << 24]; // 16MB
static int opos;

static char label_buf[100005 * 7]; 
static int label_off[100006];     
static int label_len[100005];      

static void precompute_labels(int N) {
    static const char d2[] =
        "00010203040506070809101112131415161718192021222324252627282930313233343536373839"
        "40414243444546474849505152535455565758596061626364656667686970717273747576777879"
        "8081828384858687888990919293949596979899";
    int pos = 0;
    for (int i = 0; i <= N; i++) {
        label_off[i] = pos;
        if (i == 0) { label_buf[pos++] = '0'; label_len[i] = 1; continue; }
        unsigned x = i;
        char tmp[8]; int p = 0;
        while (x >= 100) { unsigned idx = (x % 100) * 2; x /= 100; tmp[p++] = d2[idx+1]; tmp[p++] = d2[idx]; }
        if (x >= 10) { unsigned idx = x * 2; tmp[p++] = d2[idx+1]; tmp[p++] = d2[idx]; } else tmp[p++] = '0' + x;
        label_len[i] = p;
        for (int j = p - 1; j >= 0; j--) label_buf[pos++] = tmp[j];
    }
    label_off[N + 1] = pos;
}

static inline void write_label(int v) {
    memcpy(obuf + opos, label_buf + label_off[v], label_len[v]);
    opos += label_len[v];
}

constexpr int MAXN = 100005;
constexpr int MAXM = 300005;
constexpr int MAXHE = 600010;
constexpr int MAXF = 400010;

static long long Xf[MAXN], Yf[MAXN];
static int eu[MAXM], ev[MAXM];
static int csr_off[MAXN];
static int csr_he[MAXHE];
static int pos_in_adj[MAXHE];
static int nxt_he[MAXHE];
static int face_of_he[MAXHE];

static int dual_off[MAXF + 1];
static int dual_adj[MAXHE]; 
static int dual_deg[MAXF];

static int col[MAXF];
static int stk[MAXF], rstk[MAXF], cur_deg[MAXF];

static int tmp_off[MAXN];
static int tmp_off2[MAXF]; 

int main() {
    int ifd = open("nowhere-zero.in", O_RDONLY);
    struct stat st;
    fstat(ifd, &st);
    size_t fsz = st.st_size;
    char *mapped = (char*)mmap(NULL, fsz + 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE, ifd, 0);
    rp = mapped;

    int N = read_int(), M = read_int();
    for (int i = 1; i <= N; i++) { Xf[i] = read_fixed(); Yf[i] = read_fixed(); }
    for (int i = 0; i < M; i++) { eu[i] = read_int(); ev[i] = read_int(); }
    munmap(mapped, fsz + 4096);
    close(ifd);

    memset(csr_off, 0, (N + 2) * sizeof(int));
    for (int i = 0; i < M; i++) { csr_off[eu[i] + 1]++; csr_off[ev[i] + 1]++; }
    for (int i = 1; i <= N + 1; i++) csr_off[i] += csr_off[i - 1];
    memcpy(tmp_off, csr_off, (N + 1) * sizeof(int));
    for (int i = 0; i < M; i++) {
        csr_he[tmp_off[eu[i]]++] = 2 * i;
        csr_he[tmp_off[ev[i]]++] = 2 * i + 1;
    }

    for (int u = 1; u <= N; u++) {
        int lo = csr_off[u], hi = csr_off[u + 1];
        if (hi - lo <= 1) continue;
        std::sort(csr_he + lo, csr_he + hi, [](int ha, int hb) __attribute__((always_inline)) -> bool {
            int ea = ha >> 1, eb = hb >> 1;
            long long dxa, dya, dxb, dyb;
            if (ha & 1) { dxa = Xf[eu[ea]] - Xf[ev[ea]]; dya = Yf[eu[ea]] - Yf[ev[ea]]; }
            else        { dxa = Xf[ev[ea]] - Xf[eu[ea]]; dya = Yf[ev[ea]] - Yf[eu[ea]]; }
            if (hb & 1) { dxb = Xf[eu[eb]] - Xf[ev[eb]]; dyb = Yf[eu[eb]] - Yf[ev[eb]]; }
            else        { dxb = Xf[ev[eb]] - Xf[eu[eb]]; dyb = Yf[ev[eb]] - Yf[eu[eb]]; }
            int pa = dya > 0 ? 0 : (dya < 0 ? 1 : (dxa > 0 ? 0 : 1));
            int pb = dyb > 0 ? 0 : (dyb < 0 ? 1 : (dxb > 0 ? 0 : 1));
            if (__builtin_expect(pa != pb, 0)) return pa < pb;
            __int128 cross = (__int128)dxa * dyb - (__int128)dxb * dya;
            return cross > 0;
        });
    }

    for (int u = 1; u <= N; u++) {
        int lo = csr_off[u], hi = csr_off[u + 1];
        for (int k = lo; k < hi; k++)
            pos_in_adj[csr_he[k]] = k - lo;
    }

    int M2 = 2 * M;
    for (int h = 0; h < M2; h++) {
        int ei = h >> 1;
        int tgt = (h & 1) ? eu[ei] : ev[ei];
        int pr = pos_in_adj[h ^ 1];
        int dt = csr_off[tgt + 1] - csr_off[tgt];
        nxt_he[h] = csr_he[csr_off[tgt] + (pr == 0 ? dt - 1 : pr - 1)];
    }

    memset(face_of_he, -1, M2 * sizeof(int));
    int F = 0;
    for (int h = 0; h < M2; h++) {
        if (face_of_he[h] >= 0) continue;
        int cur = h;
        do { face_of_he[cur] = F; cur = nxt_he[cur]; } while (cur != h);
        F++;
    }

    memset(dual_deg, 0, F * sizeof(int));
    for (int ei = 0; ei < M; ei++) {
        int f1 = face_of_he[2 * ei], f2 = face_of_he[2 * ei + 1];
        if (f1 != f2) { dual_deg[f1]++; dual_deg[f2]++; }
    }
    dual_off[0] = 0;
    for (int f = 0; f < F; f++) dual_off[f + 1] = dual_off[f] + dual_deg[f];

    memcpy(tmp_off2, dual_off, F * sizeof(int));
    for (int ei = 0; ei < M; ei++) {
        int f1 = face_of_he[2 * ei], f2 = face_of_he[2 * ei + 1];
        if (f1 != f2) {
            dual_adj[tmp_off2[f1]++] = f2;
            dual_adj[tmp_off2[f2]++] = f1;
        }
    }

    for (int f = 0; f < F; f++) {
        int lo = dual_off[f], hi = dual_off[f + 1];
        if (hi - lo <= 1) continue;
        std::sort(dual_adj + lo, dual_adj + hi);
        int w = lo + 1;
        for (int r = lo + 1; r < hi; r++)
            if (dual_adj[r] != dual_adj[r - 1])
                dual_adj[w++] = dual_adj[r];
        dual_deg[f] = w - lo;
    }

    {
        int stop = 0, rpos = 0;
        for (int f = 0; f < F; f++) {
            cur_deg[f] = dual_deg[f];
            if (cur_deg[f] < 6) stk[stop++] = f;
        }
        while (stop > 0) {
            int f = stk[--stop];
            if (cur_deg[f] < 0) continue;
            rstk[rpos++] = f;
            cur_deg[f] = -1;
            int lo = dual_off[f], end = lo + dual_deg[f];
            for (int j = lo; j < end; j++) {
                int g = dual_adj[j];
                if (cur_deg[g] >= 0 && --cur_deg[g] < 6)
                    stk[stop++] = g;
            }
        }

        memset(col, 0, F * sizeof(int));
        for (int i = rpos - 1; i >= 0; i--) {
            int f = rstk[i];
            unsigned used = 0;
            int lo = dual_off[f], end = lo + dual_deg[f];
            for (int j = lo; j < end; j++)
                used |= 1u << col[dual_adj[j]];
            used |= 1u;
            col[f] = __builtin_ctz(~used);
        }
    }

    precompute_labels(N);
    opos = 0;

    for (int ei = 0; ei < M; ei++) {
        int flow = col[face_of_he[2 * ei]] - col[face_of_he[2 * ei + 1]];
        if (flow > 0) {
            write_label(eu[ei]); obuf[opos++] = ' ';
            write_label(ev[ei]); obuf[opos++] = ' ';
            obuf[opos++] = '0' + flow;
        } else {
            write_label(ev[ei]); obuf[opos++] = ' ';
            write_label(eu[ei]); obuf[opos++] = ' ';
            obuf[opos++] = '0' + (-flow);
        }
        obuf[opos++] = '\n';
    }

    int ofd = open("nowhere-zero.out", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    write(ofd, obuf, opos);
    close(ofd);
    return 0;
}