Cod sursa(job #987370)

Utilizator tzipleatudTudor Tiplea tzipleatud Data 20 august 2013 15:33:15
Problema Nowhere-zero Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.29 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <cstring>
#include <cmath>

#define NM 100010
#define MM 400010
#define x first
#define y second

using namespace std;

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

typedef pair<int, int> PI;
typedef pair<double, double> PD;

int N, M;
vector<int> G[NM];
PD Points[NM], Center;

map<PI, int> WallCode, WallValue;
map<PI, bool> WallVisited;
int WallZones[MM];

int NoZones;
set<int> GZones[MM];
bool Exists[MM];
int Degree[MM], ZoneColor[MM];

bool CompareByTan (int a, int b)
{
    return atan2(Points[a].y-Center.y, Points[a].x-Center.x) < atan2(Points[b].y-Center.y, Points[b].x-Center.x);
}

void Read ()
{
    f >> N >> M;
    for (int i=1; i<=N; i++)
        f >> Points[i].x >> Points[i].y;

    for (int i=1; i<=M; i++)
    {
        int a, b;
        f >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);

        WallCode[make_pair(a, b)]=M;
        WallCode[make_pair(b, a)]=i+M;
    }

    f.close();
}

void SortG ()
{
    for (int i=1; i<=N; i++)
    {
        Center=Points[i];
        sort(G[i].begin(), G[i].end(), CompareByTan);
    }
}

int SearchPosition (int center, int next)
{
    int P=0, U=G[center].size()-1, M, ANS=-1;
    int vec;

    double tan = atan2(Points[next].y-Points[center].y, Points[next].x-Points[center].x);

    while (P<=U)
    {
        M=(P+U)/2;
        vec=G[center][M];

        if (atan2(Points[vec].y-Points[center].y, Points[vec].x-Points[center].y) <= tan)
        {
            ANS=M;
            P=M+1;
        }
        else
            U=M-1;
    }

    return ANS;
}

inline int next (int i, int size)
{
    return (i<size-1?i+1:0);
}

inline int prev (int i, int size)
{
    return (i>0?i-1:size-1);
}

bool GoOnWalls (int source, int father, int node)
{
    if (node==source)
    {
        ++NoZones;
        return 1;
    }

    int position=SearchPosition(node, father);
    bool found = 0;
    int i=-1, j=-1, k, size=G[node].size();

    for (i=next(position, size); i!=position; i=next(i, size))
        if (!WallVisited[make_pair(node, G[node][i])])
        {
            found=1;
            break;
        }

    for (j=prev(position, size); j!=position; j=prev(j, size))
        if (!WallVisited[make_pair(node, G[node][j])])
        {
            found=1;
            break;
        }

    if (i==position) i=-1;
    if (j==position) j=-1;

    if (found==0 || (i==-1 && j==-1)) return 0;

    if (i==-1)
        k=G[node][j];
    else
    {
        if (j==-1)
            k=G[node][i];
        else
        {
            if (Points[father].x<Points[node].x || (Points[father].x<Points[node].x && Points[father].y>Points[node].y))
                k=G[node][j];
            else
                k=G[node][i];
        }
    }

    WallVisited[make_pair(node, k)]=1;
    found = GoOnWalls(source, node, k);

    if (found==1)
    {
        WallZones[WallCode[make_pair(node, k)]]=NoZones;
        return 1;
    }

    WallVisited[make_pair(node, k)]=0;
    return 0;
}

void BuildZones ()
{
    int i;
    vector<int>::iterator it;

    for (i=1; i<=N; i++)
        for (it=G[i].begin(); it!=G[i].end(); ++it)
            if (!WallVisited[make_pair(i, *it)])
            {
                WallVisited[make_pair(i, *it)]=1;
                bool ok=GoOnWalls(i, i, *it);
                int code=WallCode[make_pair(i, *it)];

                if (ok)
                    WallZones[code]=NoZones;
                else
                    WallVisited[make_pair(i, *it)]=0;
            }
}

void BuildGraph ()
{
    int i;
    vector<int>::iterator it;

    for (i=1; i<=N; i++)
        for (it=G[i].begin(); it!=G[i].end(); ++it)
            if (i<*it)
            {
                int zone1 = WallZones[WallCode[make_pair(i, *it)]];
                int zone2 = WallZones[WallCode[make_pair(*it, i)]];

                if (zone1!=0 && zone2!=0)
                {
                    GZones[zone1].insert(zone2);
                    GZones[zone2].insert(zone1);
                }
            }
}

void ColorZones ()
{
    stack<int> MyStack;
    set<PI> MySet;
    set<PI>::iterator set1, set2;
    set<int>::iterator it;

    for (int i=1; i<=NoZones; i++)
    {
        Exists[i]=1;
        Degree[i]=GZones[i].size();

        MySet.insert(make_pair(Degree[i], i));
    }

    while (!MySet.empty())
    {
        set1=MySet.begin();
        int node = set1->second;
        MySet.erase(set1);

        if (Exists[node]==0) continue;

        MyStack.push(node);
        Exists[node]=0;

        for (it=GZones[node].begin(); it!=GZones[node].end(); ++it)
            if (Exists[*it])
            {
                set1=MySet.find(make_pair(Degree[*it], *it));
                if (set1==MySet.end()) continue;

                MySet.erase(set1);
                Degree[*it]--;
                MySet.insert(make_pair(Degree[*it], *it));
            }
    }

    bool Marked[7];
    while (!MyStack.empty())
    {
        int node = MyStack.top();
        MyStack.pop();

        for (int i=0; i<=6; i++)
            Marked[i]=0;

        for (it=GZones[node].begin(); it!=GZones[node].end(); ++it)
            Marked[ZoneColor[*it]]=1;

        for (int i=1; i<=6; i++)
            if (Marked[i]==0)
            {
                ZoneColor[node]=i;
                break;
            }
    }
}

void Print ()
{
    int i;
    vector<int>::iterator it;

    for (i=1; i<=N; i++)
        for (it=G[i].begin(); it!=G[i].end(); ++it)
            if (i<*it)
            {
                int zone1 = WallZones[WallCode[make_pair(i, *it)]];
                int zone2 = WallZones[WallCode[make_pair(*it, i)]];

                if (ZoneColor[zone1]>ZoneColor[zone2])
                    g << i << ' ' << (*it) << ' ' << (ZoneColor[zone1] - ZoneColor[zone2]) << '\n';
                else
                    g << (*it) << ' ' << i << ' ' << (ZoneColor[zone2] - ZoneColor[zone1]) << '\n';
            }

    g.close();
}

int main ()
{
    Read();
    SortG();
    BuildZones();
    BuildGraph();
    ColorZones();
    Print();

    return 0;
}