Cod sursa(job #964891)

Utilizator mihai995mihai995 mihai995 Data 22 iunie 2013 16:47:14
Problema Nowhere-zero Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.09 kb
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <cstring>
#include <set>
using namespace std;

const int N = 600005, M = N, cMax = 7;

template<class T>
class Stiva{
    T v[M];
    int size;

public:
    Stiva(){
        size = 0;
    }

    inline void push(T x){
        v[++size] = x;
    }

    inline T top(){
        return v[size];
    }

    inline void pop(){
        --size;
    }

    inline bool empty(){
        return size == 0;
    }
};

struct Per{
    int x, y;

    Per(){
        x = y = 0;
    }

    Per(int _x, int _y){
        x = _x;
        y = _y;
    }

    inline bool operator<(const Per& N) const {
        return x > N.x;
    }
};

struct Muchie{
    int ind, next;
    double alpha;

    Muchie(int _ind, int _next, double _alpha){
        ind = _ind;
        next =_next;
        alpha = _alpha;
    }

    inline bool operator<(const Muchie& M) const {
        return alpha < M.alpha;
    }
};

int color[N], nrV, nrE, nrC;
double X[N], Y[N];
bool use[N];
vector<int> area[M], comp[M], areaGraph[M];
vector<Muchie> graph[N];
Per edge[M];
Muchie minusUnu = Muchie(-1, 0, 0);

ifstream in("nowhere-zero.in");
ofstream out("nowhere-zero.out");

inline double unghi(int x, int y){
    return atan2(Y[y] - Y[x], X[y] - X[x]);
}

inline void addToGraph(int x, int y, int ind){
    graph[x].push_back(Muchie(ind, y, unghi(x, y)));
}

void read(){
    int x, y;

    in >> nrV >> nrE;

    for (int i = 1 ; i <= nrV ; i++)
        in >> X[i] >> Y[i];

    for (int i = 1 ; i <= nrE ; i++){
        in >> x >> y;
        edge[i] = Per(x, y);

        addToGraph(x, y, i);
        addToGraph(y, x, i);
    }

    for (int i = 1 ; i <= nrV ; i++)
        if (!graph[i].empty())
            sort(graph[i].begin(), graph[i].end());
}

int mex(vector<int>& v, int val[]){
    for (int i = 0 ; i < cMax ; i++)
        use[i] = false;

    for (vector<int> :: iterator it = v.begin() ; it != v.end() ; it++)
        use[ val[*it] ] = true;

    for (int i = 1 ; i < cMax ; i++)
        if (!use[i])
            return i;
    return -1;
}

void colorare(vector<int> graph[], int color[], int n){
    int grad[n + 1];

    priority_queue<Per> Q;
    Stiva<int> S;

    for (int i = 1 ; i <= n ; i++){
        grad[i] = graph[i].size();
        Q.push(Per(grad[i], i));
        use[i] = false;
    }

    while (!Q.empty()){
        int x = Q.top().y; Q.pop();

        if (use[x])
            continue;
        use[x] = true;

        S.push(x);
        for (vector<int> :: iterator it = graph[x].begin() ; it != graph[x].end() ; it++){
            --grad[*it];
            Q.push(Per(grad[*it], *it));
        }
    }

    while (!S.empty()){
        color[S.top()] = mex(graph[S.top()], color);
        S.pop();
    }
}

Muchie& find(vector<Muchie>& v, double alpha){
    if (v.size() == 1 && v[0].alpha == alpha)
        return minusUnu;

    if (v.back().alpha <= alpha)
        return v[0];

    int rez = 0;

    for (int step = 1 << 16 ; step ; step >>= 1)
        if (rez + step < v.size() && v[rez + step].alpha <= alpha)
            rez += step;

    return v[rez + 1];
}

inline int semn(bool b){
    return b ? 1 : -1;
}

void expand(int src, Muchie& M){
    if (M.ind == -1)
        return;

    area[nrC].push_back(M.ind);
    comp[ M.ind ].push_back(nrC * semn(edge[ M.ind ].y == M.next));
    M.ind = -1;

    if (use[M.next])
        return;

    use[M.next] = true;

    expand(M.next, find(graph[M.next], unghi(M.next, src)));

    use[M.next] = false;
}

void adauga(int x, int y){
    x = abs(x);
    y = abs(y);

    areaGraph[x].push_back(y);
    areaGraph[y].push_back(x);
}

void buildGraph(vector<Muchie> graph[]){
    memset(use, false, sizeof(use));

    for (int i = 1 ; i <= nrV ; i++){
        use[i] = true;

        for (size_t j = 0 ; j < graph[i].size() ; j++)
            if (graph[i][j].ind != -1){
                ++nrC;
                expand(i, graph[i][j]);
            }

        use[i] = false;
    }

    for (int i = 1 ; i <= nrE ; i++)
        if (comp[i].size() > 1)
            adauga(comp[i][0], comp[i][1]);
}

void print(Per P, int x, int y){
    int val = 0;

    if (x > 0)
        val += color[x];
    else
        val -= color[-x];

    if (y > 0)
        val += color[y];
    else
        val -= color[-y];

    if (val > 0)
        out << P.x << " " << P.y << " " << val << "\n";
    else
        out << P.y << " " << P.x << " " << -val << "\n";
}

void cleanup(vector<int>& v){
    sort(v.begin(), v.end());

    int n = 1;
    for (size_t i = 1 ; i < v.size() ; i++)
        if (v[i] != v[i - 1])
            v[n++] = v[i];
    v.resize(n);
}

int main(){
    read();

    buildGraph(graph);

    for (int i = 1 ; i <= nrC ; i++)
        cleanup(areaGraph[i]);

    colorare(areaGraph, color, nrC);

    for (int i = 1 ; i <= nrE ; i++)
        print(edge[i], comp[i][0], comp[i][1]);

    return 0;
}