Cod sursa(job #1261069)

Utilizator andreiiiiPopa Andrei andreiiii Data 11 noiembrie 2014 21:57:27
Problema Nowhere-zero Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.9 kb
#include <algorithm>
#include <bitset>
#include <cstdio>
#include <cassert>
#include <cmath>
#include <vector>

using namespace std;

const int Nmax = 100005, Mmax = Nmax * 3;

struct Point {
    double x, y;
};

Point points[Nmax];
pair<int, int> edges[Mmax], eedges[Mmax], Pos[Mmax];
int Capacity[Mmax];

vector<int> G[Nmax], Gz[Mmax];
vector<bool> usedEdge[Nmax];

int Zone[Mmax][2], Color[Mmax];

int deg[Mmax];
bitset<Mmax> used;

void getZone(int node, int edge, int zone) {
    int start = node;
    do {
        usedEdge[node][edge] = true;
        int p = G[node][edge];
        int next = edges[p].first ^ edges[p].second ^ node;
        if (Zone[p][0]) Zone[p][1] = zone;
        else {
            Zone[p][0] = zone;
            edges[p] = {node, next};
        }
        edge = ((next == eedges[p].first ? Pos[p].first: Pos[p].second) + 1) % G[next].size();
        node = next;
    } while(node != start);
}

int getZones(int N, int M) {
    int czones = 0;
    for (int i = 1; i <= N; ++i) {
        sort(G[i].begin(), G[i].end(), [i](const int a, const int b) {
            int node1 = edges[a].first ^ edges[a].second ^ i;
            int node2 = edges[b].first ^ edges[b].second ^ i;
            return atan2(points[node1].y - points[i].y, points[node1].x - points[i].x) < atan2(points[node2].y - points[i].y, points[node2].x - points[i].x);
        });
        usedEdge[i].resize(G[i].size(), false);
        for (int j = 0; j < int(G[i].size()); ++j) {
            int p = G[i][j];
            (i == edges[p].first ? Pos[p].first: Pos[p].second) = j;
        }
    }

    for (int i = 1; i <= N; ++i) {
        for (int j = 0; j < int(G[i].size()); ++j) {
            if (!usedEdge[i][j])
                getZone(i, j, ++czones);
        }
    }

    //assert(czones == 2 + M - N);
    return czones;
}

void buildZoneGraph(int N, int M) {
    for (int i = 1; i <= M; ++i) {
        Gz[Zone[i][0]].push_back(Zone[i][1]);
        Gz[Zone[i][1]].push_back(Zone[i][0]);
    }
}

void colorNewGraph(int N) {
    vector<int> order;
    order.reserve(N);
    for (int i = 1; i <= N; ++i) {
        deg[i] = Gz[i].size();
        if (deg[i] < 6) {
            order.push_back(i);
            used[i] = 1;
        }
    }

    for (int i = 0; i < N; ++i) {
        int node = order[i];

        for (int p: Gz[node]) {
            deg[p]--;
            if (!used[p] && deg[p] < 6) {
                used[p] = 1;
                order.push_back(p);
            }
        }
    }
    reverse(order.begin(), order.end());
    assert(int(order.size()) == N);

    for (int node: order) {
        char usedCol = 0;
        for (int p: Gz[node])
            usedCol |= 1 << Color[p];

        for (int i = 1; ; ++i) {
            if (!(usedCol & (1 << i))) {
                Color[node] = i;
                break;
            }
        }
    }
}

void setEdges(int N, int M) {
    for (int i = 1; i <= M; ++i) {
        Capacity[i] = Color[Zone[i][1]] - Color[Zone[i][0]];
        if (Capacity[i] < 0) {
            Capacity[i] = -Capacity[i];
            swap(edges[i].first, edges[i].second);
        }
    }
}

void writeAnswer(int N, int M) {
    for (int i = 1; i <= M; ++i)
        printf("%d %d %d\n", edges[i].first, edges[i].second, Capacity[i]);
}

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

    int N, M;
    scanf("%d%d", &N, &M);

    for (int i = 1; i <= N; ++i)
        scanf("%lf%lf", &points[i].x, &points[i].y);

    for (int i = 1; i <= M; ++i) {
        scanf("%d%d", &edges[i].first, &edges[i].second);
        eedges[i] = edges[i];
        G[edges[i].first].push_back(i);
        G[edges[i].second].push_back(i);
    }

    int czones = getZones(N, M);
    buildZoneGraph(N, M);
    colorNewGraph(czones);
    setEdges(N, M);
    writeAnswer(N, M);
}