Cod sursa(job #962789)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 15 iunie 2013 17:36:57
Problema Nowhere-zero Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.25 kb
#include <cstdio>
#include <cmath>
#include <cassert>

#include <algorithm>
#include <vector>
#include <queue>
#include <stack>

#define x first
#define y second

using namespace std;

typedef pair<double, double> Point;
typedef pair<int, int> Edge;

const int MAX_COLOR = 7;

vector<Point> Points;
vector<double> Alpha;
vector<vector<int>> G, RegionG;
int V, E, R;
vector<Edge> Edges;
vector<int> Next, RegionIndex, Colors;
vector<vector<int>> Regions;

inline int ReverseIndex(const int index) {
    if (index < E)
        return index + E;
    return index - E;
}

void BuildGraph() {
    Next.resize(2 * E);
    for (int x = 0; x < V; ++x) {
        for (auto &e: G[x])
            Alpha[e] = atan2(Points[Edges[e].y].y - Points[x].y, Points[Edges[e].y].x - Points[x].x);
        sort(G[x].begin(), G[x].end(), [](const int &e1, const int &e2) -> bool {
             return Alpha[e1] < Alpha[e2];
        });
        for (int i = 0; i < static_cast<int>(G[x].size()); ++i)
            Next[G[x][i]] = ReverseIndex(G[x][(i + 1) % static_cast<int>(G[x].size())]);
    }
}

void BuildRegions() {
    RegionIndex.resize(2 * E);
    vector<bool> usedEdges = vector<bool>(2 * E, false);
    for (int x = 0; x < V; ++x) {
        for (auto e: G[x]) {
            vector<int> region;
            for (; !usedEdges[e]; e = Next[e]) {
                region.push_back(e);
                RegionIndex[e] = static_cast<int>(Regions.size());
                usedEdges[e] = true;
            }
            if (!region.empty())
                Regions.push_back(region);
        }
    }
    R = static_cast<int>(Regions.size());
    RegionG.resize(R);
    Colors.resize(R);
}

void BuildRegionGraph() {
    for (int i = 0; i < E; ++i) {
        int x = RegionIndex[i], u = RegionIndex[ReverseIndex(i)];
        RegionG[x].push_back(u); RegionG[u].push_back(x);
    }
    for (int x = 0; x < R; ++x) {
        sort(RegionG[x].begin(), RegionG[x].end());
        RegionG[x].erase(unique(RegionG[x].begin(), RegionG[x].end()), RegionG[x].end());
    }
}

inline int GetColor(const int x) {
    vector<bool> used = vector<bool>(MAX_COLOR, false);
    for (auto &y: RegionG[x])
        used[Colors[y]] = true;
    for (int color = 1; color < MAX_COLOR; ++color)
        if (!used[color])
            return color;
    return 0;
}

void ColorRegions() {
    vector<int> degrees = vector<int>(R, 0);
    for (int x = 0; x < R; ++x)
        degrees[x] = static_cast<int>(RegionG[x].size());
    stack<int> order;
    queue<int> q;
    vector<bool> used = vector<bool>(R, false);
    for (int x = 0; x < R; ++x) {
        if (degrees[x] < MAX_COLOR - 1) {
            q.push(x);
            used[x] = true;
        }
    }
    for (; !q.empty(); q.pop()) {
        int x = q.front();
        order.push(x);
        for (auto &y: RegionG[x]) {
            --degrees[y];
            if (degrees[y] < MAX_COLOR - 1 && !used[y]) {
                q.push(y);
                used[y] = true;
            }
        }
    }
    for (int x = 0; x < R; ++x)
        Colors[x] = 0;
    for (; !order.empty(); order.pop()) {
        int x = order.top();
        Colors[x] = GetColor(x);
    }
}

void Solve() {
    BuildGraph();
    BuildRegions();
    BuildRegionGraph();
    ColorRegions();
}

void Read() {
    assert(freopen("nowhere-zero.in", "r", stdin));
    assert(scanf("%d %d", &V, &E) == 2);
    G.resize(V);
    Points.resize(V);
    Alpha.resize(2 * E);
    Edges.resize(2 * E);
    for (int i = 0; i < V; ++i)
        assert(scanf("%lf %lf", &Points[i].x, &Points[i].y) == 2);
    for (int i = 0; i < E; ++i) {
        int x, y; assert(scanf("%d %d", &x, &y) == 2);
        --x; --y;
        Edges[i] = Edge(x, y);
        Edges[ReverseIndex(i)] = Edge(y, x);
        G[x].push_back(i); G[y].push_back(ReverseIndex(i));
    }
}

void Print() {
    assert(freopen("nowhere-zero.out", "w", stdout));
    for (int i = 0; i < 2 * E; ++i) {
        int flow = Colors[RegionIndex[i]] - Colors[RegionIndex[ReverseIndex(i)]];
        if (flow < 0)
            continue;
        printf("%d %d %d\n", Edges[i].x + 1, Edges[i].y + 1, flow);
    }
}

int main() {
    Read();
    Solve();
    Print();
    return 0;
}