Cod sursa(job #1937927)

Utilizator adriannicolaeAdrian Nicolae adriannicolae Data 24 martie 2017 13:54:45
Problema Nowhere-zero Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.78 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. 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 graf minim si 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();
}