Cod sursa(job #1168810)

Utilizator dariusdariusMarian Darius dariusdarius Data 9 aprilie 2014 17:31:47
Problema Nowhere-zero Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.06 kb
#include <cassert>
#include <cmath>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
const int MAX_N = 100005;
const double INFINITE = 1.e9;

struct PointXY {
    double x, y;
} point[MAX_N];
pair<int, int> edge[MAX_N * 6];
vector< pair<double, int> > graph[MAX_N];
vector<int> aib[MAX_N];
vector<int> face_graph[MAX_N * 3];
map< pair<int, int>, int > index;
int face[MAX_N * 6];
int color[MAX_N * 3];
bool vis[MAX_N * 3];
int deg[MAX_N * 3];

inline double angle(int u, int v) {
    return atan2(point[v].y - point[u].y, point[v].x - point[u].x);
}

void build_face(int current, int face_index) {
    int start = edge[current].first;
    while(edge[current].second != start) {
        face[current] = face_index;
        double enter = angle(edge[current].second, edge[current].first);
        int node = edge[current].second, deg = static_cast<int>(graph[node].size()) / 2;
        int pos = upper_bound(graph[node].begin(), graph[node].end(), make_pair(enter, 0)) - graph[node].begin();
        for(pos = pos + 1; aib[node][pos] == 0 && pos <= 2 * deg; ++ pos);
        assert(pos <= 2 * deg);
        aib[node][pos] = 0;
        if(pos <= deg) {
            aib[node][pos + deg] = 0;
        } else {
            aib[node][pos - deg] = 0;
        }
        current = index[make_pair(node, graph[node][pos].second)];
    }
    face[current] = face_index;
}

inline int get_color(int node) {
    int f[7] = {0};
    for(vector<int> :: iterator it = face_graph[node].begin(); it != face_graph[node].end(); ++ it) {
        f[color[*it]] = 1;
    }
    for(int i = 1; i < 7; ++ i) {
        if(!f[i]) {
            return i;
        }
    }
    return 0;
}
void color_faces(int n) {
    vector<int> order;
    int first = 0;
    for(int i = 1; i <= n; ++ i) {
        deg[i] = static_cast<int>(face_graph[i].size());
        if(deg[i] < 6) {
            order.push_back(i);
            vis[i] = true;
        }
    }
    while(first < static_cast<int>(order.size())) {
        int node = order[first];
        ++ first;
        for(vector<int> :: iterator it = face_graph[node].begin(); it != face_graph[node].end(); ++ it) {
            -- deg[*it];
            if(deg[*it] < 6 && !vis[*it]) {
                order.push_back(*it);
                vis[*it] = true;
            }
        }
    }
    for(int i = n - 1; i >= 0; -- i) {
        color[i] = get_color(i);
    }
}

int main() {
    ifstream fin("nowhere-zero.in");
    ofstream fout("nowhere-zero.out");
    int n, m;
    
    fin >> n >> m;
    for(int i = 1; i <= n; ++ i) {
        fin >> point[i].x >> point[i].y;
        graph[i].push_back(make_pair(-INFINITE, 0));
    }
    for(int i = 1; i <= m; ++ i) {
        int x, y;
        fin >> x >> y;
        graph[x].push_back(make_pair(angle(x, y), y));
        graph[y].push_back(make_pair(angle(y, x), x));
        edge[i] = make_pair(x, y);
        edge[i + m] = make_pair(y, x);
        index[edge[i]] = i;
        index[edge[i + m]] = i + m;
    }
    for(int i = 1; i <= n; ++ i) {
        sort(graph[i].begin(), graph[i].end());
        int deg = static_cast<int>(graph[i].size()) - 1;
        graph[i].resize(2 * deg + 1);
        aib[i].assign(2 * deg + 1, 1);
        for(int j = 1; j <= deg; ++ j) {
            graph[i][j + deg] = make_pair(graph[i][j].first + 2 * M_PI, graph[i][j].second);
        }
    }

    int faces = 0;
    for(int i = 1; i <= 2 * m; ++ i) {
        if(!face[i]) {
            build_face(i, ++ faces);
        }
    }
    for(int i = 1; i <= m; ++ i) {
        if(face[i] != face[m + i]) {
            face_graph[face[i]].push_back(face[m + i]);
            face_graph[face[m + i]].push_back(face[i]);
        }
    }
    color_faces(faces);

    for(int i = 1; i <= m; ++ i) {
        if(color[face[i]] < color[face[i + m]]) {
            fout << edge[i].second << " " << edge[i].first << " " << color[face[i + m]] - color[face[i]] << "\n";
        } else {
            fout << edge[i].first << " " << edge[i].second << " " << color[face[i]] - color[face[i + m]] << "\n";
        }
    }
    return 0;
}