Cod sursa(job #1024987)

Utilizator danalex97Dan H Alexandru danalex97 Data 9 noiembrie 2013 13:19:32
Problema Nowhere-zero Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.91 kb
#include <fstream>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;

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

/**

Construiesc regiunile si trag muchie intre pentru laturile comune din regiuni diferite.
Muchiile initiale le orientez. Intai fac un vector nxt care as ma trimita la urmatorul
punct. ( punctele vor fi sortea in ordine trigonometrica ) Cand ajung in acelasi punct
am epuziat o regiune.

Colorez graful regiunilor si apoi contruiesc reteaua de circulatie. Colorarea se face cu
6 culori , deci pornesc de la nodul cu grad minim si il elimin din graf.

Complexitatea: O(N log N)

*/

const int debuging = 0;

#define IT(type) vector<type>::iterator
#define parc(type,it,vect) for (vector< type >::iterator it=vect.begin();it!=vect.end();++it)

#define x first
#define y second

const int Nmax = 100010;

int N,M,K;
vector< pair<double,double> > point;
vector< pair<int,int> > edges;
vector<int> V[Nmax];
vector< vector<int> > regions;
vector<int> r_index;
vector< vector<int> > graph;
vector<int> nxt;
vector<double> angle;

int reverse_index(int x)
{
    if ( x > M )
        return x-M;
    return x+M;
}

void print_vector(vector<int> A)
{
    if ( !debuging ) return;
    G<<"debug: ";
    for (size_t i=0;i<A.size();++i)
        G<<A[i]<<' ';
    G<<'\n';
}

void read_data()
{
    F>>N>>M;
    point.resize(N+5);
    for (int i=1;i<=N;++i)
        F>>point[i].x>>point[i].y;
    edges.resize(2*M+5);
    for (int i=1,x,y;i<=M;++i)
    {
        F>>x>>y;
        edges[i] = make_pair(x,y);
        edges[reverse_index(i)] = make_pair(y,x);
        V[x].push_back( i );
        V[y].push_back( reverse_index(i) );
    }
}

bool angle_cmp(int x,int y)
{
    return angle[x] < angle[y];
}

void compute_nxt()
{
    angle.resize(2*M+5);
    nxt.resize(2*M+5);
    for (int i=1;i<=N;++i)
    {
        parc(int,e,V[i])
            angle[*e] = atan2(point[edges[*e].y].y-point[i].y,point[edges[*e].y].x-point[i].x);
        sort(V[i].begin(),V[i].end(),angle_cmp);
        for (size_t j=0;j<V[i].size();++j)
            nxt[reverse_index(V[i][j])] = V[i][(j+1)%(int(V[i].size()))];
    }
}

vector<bool> used;

void build_regions()
{
    used.resize(2*M+5);
    r_index.resize(2*M+5);
    for (int x=1;x<=N;++x)
        parc(int,nowe,V[x])
        {
            int e = *nowe;
            vector<int> region;
            for (;used[e] == 0 && edges[e].y != x ; e = nxt[e])
            {
                region.push_back(e);
                r_index[e] = int(regions.size());
                used[e] = 1;
            }
            if ( !used[e] )
            {
                region.push_back(e);
                r_index[e] = int(regions.size());
                used[e] = 1;
            }
            print_vector( region );
            if ( region.size() )
                regions.push_back( region );
        }
    K = regions.size();
}

void place_edges()
{
    graph.resize(K+5);
    for (int i=1;i<=M;++i)
    {
        graph[ r_index[i] ].push_back( r_index[reverse_index(i)] );
        graph[ r_index[reverse_index(i)] ].push_back( r_index[i] );
    }
    for (int i=0;i<K;++i)
    {
        sort(graph[i].begin(),graph[i].end());
        graph[i].erase( unique(graph[i].begin(),graph[i].end()) , graph[i].end() );
        print_vector(graph[i]);
    }
}

const int Colors = 6;

queue<int> q;
vector<int> degree;
vector<int> order;
vector<int> color;
vector<int> mark;

int get_color(int node)
{
    int X[Colors+5];
    memset(X,0,sizeof(X));
    print_vector(graph[node]);
    parc(int,it,graph[node])
        X[color[*it]] = 1;
    for (int i=1;i<=Colors;++i)
        if ( X[i] == 0 )
            return i;
    return 0;
}

void color_graph()
{
    degree.resize(K+5);
    mark.resize(K+5);
    color.resize(K+5);
    for (int i=0;i<K;++i)
        degree[i] = int(graph[i].size());
    for (int i=0;i<K;++i)
        if ( degree[i] < Colors )
        {
            mark[i] = 1;
            q.push( i );
        }
    while ( q.size() )
    {
        int now = q.front();
        order.push_back( now );
        q.pop();
        parc(int,it,graph[now])
        {
            --degree[*it];
            if ( degree[*it] < Colors && mark[*it] == 0 )
            {
                mark[*it] = 1;
                q.push(*it);
            }
        }
    }
    for (int i=int(order.size())-1;i>=0;--i)
        color[ order[i] ] = get_color(order[i]);
}

void print_data()
{
    for (int i=1;i<=(M<<1);++i)
    {
        int flow = color[ r_index[i] ] - color[ r_index[reverse_index(i)] ];
        if ( flow < 0 ) continue;
        G<<edges[i].x<<' '<<edges[i].y<<' '<<flow<<'\n';
    }
}

int main()
{
    read_data();
    compute_nxt();
    build_regions();
    place_edges();
    color_graph();
    print_data();
}