Cod sursa(job #959451)

Utilizator goguGogu Marian gogu Data 8 iunie 2013 12:57:31
Problema Nowhere-zero Scor 20
Compilator cpp Status done
Runda Infoarena Cup 2013 Marime 3.55 kb
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>

using namespace std;

#define MaxN 100100
#define sqr(x) ((x) * (x))

struct Edge {
    int vec, flux;
    Edge(int v) {
        vec = v;
        flux = 0;
    }
};

pair<double, double> points[MaxN];

int N, M, doneEdges = 0;
vector<Edge> edges[MaxN];
int cd[MaxN], t[MaxN];
bool viz[MaxN], haveTouched[MaxN];
int startNode = 0, sizeCd = 0;
bool stillCycling;

void SetTata(int poz, int val) {
    t[poz] = val;
    cd[sizeCd++] = poz;
}

void ClearTati() {
    for (int i = 0; i < sizeCd; i++) {
        t[cd[i]] = -1;
    }
    sizeCd = 0;
}

bool CompFlux(const Edge &a, const Edge &b) {
    return a.flux < b.flux;
}

double GetDist(int x, const Edge &a) {
    const int y = a.vec;
    return sqrt(sqr(points[x].first - points[y].first) + sqr(points[x].first - points[y].first));
}

bool CompFluxDist(const Edge &a, const Edge &b) {
    if (a.flux != b.flux) {
        return a.flux < b.flux;
    } else {
        return GetDist(startNode, a) > GetDist(startNode, b);
    }
}

void IncremFlow(int x, int y, int flux) {
    for (size_t i = 0; i < edges[x].size(); i++) {
        if (edges[x][i].vec == y) {
            doneEdges += (edges[x][i].flux == 0 && flux > 0);
            edges[x][i].flux += flux;
            return;
        }
    }
}

void MarkEdge(int x, int y) {
    IncremFlow(x, y, 1);
    IncremFlow(y, x, -1);
}

bool HaveEdges(int x) {
    for (size_t i = 0; i < edges[x].size(); i++) {
        if (edges[x][i].flux == 0) {
            return true;
        }
    }
    return false;
}

void ReversePath(int nod) {
    MarkEdge(nod, startNode);
    while (nod != startNode) {
        MarkEdge(t[nod], nod);
        nod = t[nod];
    }
}

//ar trebui facute mai multe cautari in acelasi timp
void df(int nod) {
    sort(edges[nod].begin(), edges[nod].end(), CompFluxDist);
    for (int i = 0; i < (int)edges[nod].size() && stillCycling; i++) {
        const int vec = edges[nod][i].vec;
        if (edges[nod][i].flux >= 0 && t[vec] == -1 && vec != t[nod]) {

            if (vec == startNode) {
                stillCycling = false;
                ReversePath(nod);
                return;
            }

            SetTata(vec, nod);
            df(vec);
        }
    }
}

void FindCycle() {
    while (!HaveEdges(startNode) && startNode < N) {
        startNode++;
    }

    stillCycling = true;

    for (size_t i = 0; i < edges[startNode].size(); i++) {
        if (edges[startNode][i].flux == 0) {
            const int v = edges[startNode][i].vec;
            SetTata(v, startNode);
            df(v);
            ClearTati();
            return;
        }
    }
}

int main() {
    freopen("nowhere-zero.in", "rb", stdin);
    freopen("nowhere-zero.out", "wb", stdout);
    scanf("%d %d\n", &N, &M);

    for (int i = 0; i < N; i++) {
        scanf("%lf %lf", &points[i].first, &points[i].second);
    }

    for (int i = 0; i < M; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        x--; y--;
        edges[x].push_back(y);
        edges[y].push_back(x);
    }

    memset(t, -1, sizeof(int) * N);

    while (doneEdges < M) {
        FindCycle();
    }

    for (int i = 0; i < N; i++) {
        for (size_t j = 0; j < edges[i].size(); j++) {
            if (edges[i][j].flux > 0) {
                printf("%d %d %d\n", i + 1, edges[i][j].vec + 1, edges[i][j].flux);
            }
        }
    }

    return 0;
}