Cod sursa(job #1928952)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 16 martie 2017 21:53:32
Problema Nowhere-zero Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.17 kb
// la un cod corect

// libraria citirii si afisarii cu scanf si printf
// multa sanatate!

#include <cstdio>

// sefu la atan2, ne traiasca!

#include <cmath>

// baiatu cu sort

#include <algorithm>

// pt mapuri

#include <utility>

// pt graf

#include <map>

// marimea pateului

#define MAXN 100000
#define MAXK 200009
#define MAXM 600099

// structura mea favorita, mycreation

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

//aicisa niste declarari

int sef;
std::vector <bool> viz[MAXN+1];
std::vector <myc> g[MAXN+1];
std::map <int, int> mp[MAXN+1];
double x[MAXN+1], y[MAXN+1];

int a[MAXM], b[MAXM], moaca[MAXM];

bool done[MAXK+1], ok[7];
int q[MAXK+1], unde[MAXK+1], gr[MAXK+1];
char cul[MAXK+1];
std::vector <int> v[MAXK+1];

// asa se sorteaza niste muchii

bool cmp(const myc &a, const myc &b){
    return atan2(y[a.x]-y[sef], x[a.x]-x[sef])<atan2(y[b.x]-y[sef], x[b.x]-x[sef]);
}

//profund...

int main(){
    FILE *fin, *fout;
    fin=fopen("nowhere-zero.in", "r");
    fout=fopen("nowhere-zero.out", "w");

    // ideea la problema asta e sa gasesti o 6-colorare a grafului fetelor
    // fiecare fata va creste fluxul de pe o muchie in sensul ei trigonometric
    // astfel fiecare muchie, in orice sens al ei, va avea costul intre -5 si 5
    // partea naspa e determinarea grafului fetelor

    // mai intai citim datele de intrare

    int n, m;
    fscanf(fin, "%d%d", &n, &m);

    for(int i=1; i<=n; i++)
        fscanf(fin, "%lf%lf", &x[i], &y[i]);

    for(int i=0; i<2*m; i+=2){
        fscanf(fin, "%d%d", &a[i], &b[i]);

        a[i+1]=b[i];
        b[i+1]=a[i];

        g[a[i]].push_back(myc(b[i], i));
        g[b[i]].push_back(myc(a[i], i+1));
    }

    // acum ar fi util ca in fiecare nod sa
    // ii tinem vecinii sortati dupa unghi

    for(int i=1; i<=n; i++){
        sef=i;
        std::sort(g[i].begin(), g[i].end(), cmp);

        // tinem un vector de vizitari ale muchiilor

        for(int j=0; j<(int)g[i].size(); j++)
            viz[i].push_back(0);

        // ne-ar ajuta sa stim si pozitiile nodurilor
        // folosim un std::map

        for(int j=0; j<(int)g[i].size(); j++)
            mp[i][g[i][j].x]=j;

    }

    return 0;

    // pana epuizam toate muchiile din graf, construim noi fet(z)e, numerotate cu k

    int k=0;
    for(int i=1; i<=n; i++){
        for(int j=0; j<(int)g[i].size(); j++) if(viz[i][j]==0){
            //ne alegem muchia

            int x=i;
            myc y=g[i][j];

            // si parcurgem noua fata determinata de muchia aleasa

            k++;
            while(y.x!=i){
                // notam fata actuala pe muchia pe care suntem

                moaca[y.y]=k;

                // marcam muchia ca vizitata

                viz[x][y.y]=1;

                // si inaintam in graf, alegand prima mukie in sens trigonometric care urmeaza

                int aux=x;
                x=y.x;
                int poz=mp[x][aux]-1;
                if(poz==-1)
                    poz=g[x].size()-1;
                y=g[x][poz];
            }

            moaca[y.y]=k;
            viz[x][y.y]=1;
        }
    }

    // e timpul sa ducem muchii prin graful feteor!

    for(int i=0; i<2*m; i+=2){
        v[moaca[i]].push_back(moaca[i+1]);
        v[moaca[i+1]].push_back(moaca[i]);
    }

    // si sa il coloram in 6 culori!
    // vom tine in permantenta o coada cu nodurile de grad <= 5

    int st=0, dr=0;
    for(int i=1; i<=k; i++){
        gr[i]=v[i].size();
        if(gr[i]<=5){
            unde[i]=dr;
            q[dr++]=i;
            done[i]=1;
        }
    }

    // parcurgem coada si o extindem pe parcurs

    while(st<dr){
        for(auto x:v[q[st]]){
            if(done[x]==0){
                gr[x]--;
                if(gr[x]==5){
                    // inseram nodul la finalul cozii

                    unde[x]=dr;
                    q[dr++]=x;
                    done[x]=1;
                }
            }
        }
        st++;
    }

    //parcurgem de la dreapta la stanga coada si calculam culoarea fiecarui nod

    for(int i=k-1; i>=0; i--){
        // calculam culoarea nodului q[i]

        for(int j=1; j<=6; j++)
            ok[j]=1;

        for(auto x:v[q[i]]){
            if(unde[x]>unde[q[i]]){
                // culoarea nodului x o influenteaza pe a mea
                // nelasandu-ma sa o fixez egala cu cul[x]

                ok[(int)cul[x]]=0;
            }
        }

        // fiind maksim 5 culori interzise, macar una va fi disponibila pentru nodul CURent

        for(int j=1; j<=6; j++)
            if(ok[j])
                cul[q[i]]=j;
    }

    // avand calculate culorile fetelor, nu mai trebuie decat sa afisam raspunsul

    for(int i=0; i<2*m; i+=2){
        int sol;
        if(cul[moaca[i]]>cul[moaca[i+1]])
            sol=i;
        else sol=i+1;

        int ans=cul[moaca[sol]]-cul[moaca[sol^1]];

        fprintf(fout, "%d %d %d\n", a[sol], b[sol], ans);
    }

    // vedem la debug ce-a iesit

    fclose(fin);
    fclose(fout);
    return 0;
}