Cod sursa(job #962268)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 14 iunie 2013 13:12:32
Problema Nowhere-zero Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.99 kb
#include <cstdio>
#include <cmath>
#include <cassert>

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

using namespace std;

typedef long long int64;

class Point {
  public:
    double x, y;

    Point() {}

    Point(const double x, const double y) {
        this->x = x;
        this->y = y;
    }
};

class Edge {
  public:
    int x, y;

    Edge() {}

    Edge(const int x, const int y) {
        this->x = x;
        this->y = y;
    }

    bool operator==(const Edge &other) const {
        return (x == other.x && y == other.y);
    }

    static Edge Reverse(const Edge &e) {
        return Edge(e.y, e.x);
    }

    class HashCode {
      public:
        int operator()(const Edge &object) const {
            return (1LL * object.x * Base + object.y) % U;
        }

      private:
        static const int Base = 100003;
        static const int U = 666013;
    };
};

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

class Compare {
  public:
    bool operator()(const int &x, const int &y) const {
        return Alpha[x] < Alpha[y];
    }
};

void BuildGraph() {
    for (int x = 0; x < V; ++x) {
        if (G[x].empty())
            continue;
        for (auto &y: G[x])
            Alpha[y] = atan2(Points[y].y - Points[x].y, Points[y].x - Points[x].x);
        sort(G[x].begin(), G[x].end(), Compare());
        G[x].push_back(G[x].front());
        for (int i = 0; i + 1 < static_cast<int>(G[x].size()); ++i)
            Next[Edge(G[x][i], x)] = G[x][i + 1];
    }
}

void BuildRegions() {
    unordered_set<Edge, Edge::HashCode> usedEdges;
    for (int x = 0; x < V; ++x) {
        for (auto &y: G[x]) {
            Edge e = Edge(x, y);
            if (usedEdges.find(e) != usedEdges.end())
                continue;
            vector<int> region;
            region.push_back(x);
            do {
                usedEdges.insert(e);
                RegionIndex[e] = static_cast<int>(Regions.size());
                region.push_back(e.y);
                e = Edge(e.y, Next[e]);
            } while (usedEdges.find(e) == usedEdges.end());
            Regions.push_back(region);
        }
    }
    R = static_cast<int>(Regions.size());
    RegionG.resize(R);
    Colors.resize(R);
}

void BuildRegionGraph() {
    unordered_set<Edge, Edge::HashCode> usedEdges;
    for (auto e: Edges) {
        int x = RegionIndex[e], y = RegionIndex[Edge::Reverse(e)];
        if (usedEdges.find(Edge(x, y)) != usedEdges.end())
            continue;
        RegionG[x].push_back(y); RegionG[y].push_back(x);
        usedEdges.insert(Edge(x, y)); usedEdges.insert(Edge(y, x));
    }
}

inline int GetColor(const int x) {
    vector<bool> used = vector<bool>(7, false);
    for (auto &y: RegionG[x])
        used[Colors[y]] = true;
    for (int color = 1; color < 7; ++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] < 6) {
            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] < 6 && !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(V);
    Edges.resize(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);
        G[x].push_back(y); G[y].push_back(x);
    }
}

void Print() {
    assert(freopen("nowhere-zero.out", "w", stdout));
    for (auto e: Edges) {
        int flow = Colors[RegionIndex[e]] - Colors[RegionIndex[Edge::Reverse(e)]];
        if (flow < 0) {
            e = Edge::Reverse(e);
            flow = -flow;
        }
        printf("%d %d %d\n", e.x + 1, e.y + 1, flow);
    }
}

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