Cod sursa(job #963189)

Utilizator mihai995mihai995 mihai995 Data 16 iunie 2013 19:31:25
Problema Nowhere-zero Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.77 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <cstring>
#include <set>
using namespace std;

const int N = 100005, M = 3 * N, cMax = 7;

template<class T>
class Stiva{
    T v[N];
    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];
set<Muchie> graph[N];
Per edge[M];

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

inline void addToGraph(int x, int y, int ind, double Y, double X){
    graph[x].insert(Muchie(ind, y, atan2(Y, X)));
}

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, Y[y] - Y[x], X[y] - X[x]);
        addToGraph(y, x, i, Y[x] - Y[y], X[x] - X[y]);
    }
}

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();
    }
}

set<Muchie> :: iterator find(set<Muchie>& S, double alpha){
    while (M_PI < alpha)
        alpha -= 2 * M_PI;

    set<Muchie> :: iterator it = S.upper_bound(Muchie(0, 0, alpha));

    return it == S.end() ? S.begin() : it;
}

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

void expand(set<Muchie>& S, set<Muchie> :: iterator it){
    if (it == S.end())
        return;

    int x = it -> next;
    double alpha = it -> alpha;

    area[nrC].push_back(it -> ind);
    comp[ it -> ind ].push_back(nrC * semn(edge[ it -> ind ].y == x));
    S.erase(it);

    if (use[x])
        return;

    use[x] = true;

    expand(graph[x], find(graph[x], M_PI + alpha));

    use[x] = 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(set<Muchie> graph[]){
    memset(use, false, sizeof(use));

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

        while (!graph[i].empty()){
            ++nrC;
            expand(graph[i], graph[i].begin());
        }

        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 (int 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;
}