Cod sursa(job #1466457)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 29 iulie 2015 11:25:13
Problema Critice Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.15 kb
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <vector>
#include <list>
#include <queue>
#include <cstdlib>
#include <cstring>
using namespace std;
#define _submit
#ifdef _submit
#define InFile "critice.in"
#define OtFile "critice.out"
#else
#define InFile "fis.in"
#define OtFile "fis.out"
#endif
 
class edge {
private:
    int toNod, flow, capacity, ID;
    edge* dup;
    edge(int n1, int n2, int cap, int nr) {
        toNod = n2;
        capacity = cap;
        flow = 0;
        ID = nr;
    }
    void assignDup(edge *E) {
        dup = E;
    }
    bool isSaturated() {
        return (capacity - flow == 0) || (capacity + flow == 0);
    }
    friend class graph;
};
 
class graph {
private:
    vector< list<edge> > adiac;
    int edgeCounter;
public:
    graph(int nrNod) {
        adiac.resize(nrNod);
        edgeCounter = 0;
    }
    void newEdge(int n1, int n2, int cap) {
        adiac[n1].push_back(edge(n1, n2, cap, edgeCounter));
        adiac[n2].push_back(edge(n2, n1, cap, edgeCounter));
        adiac[n1].back().assignDup(&adiac[n2].back());
        adiac[n2].back().assignDup(&adiac[n1].back());
        edgeCounter++;
    }
    int sendFlows(vector<int>& parent, vector<int>& capToParent, vector<int*>& flowToParent, vector<int*>& flowToParentDup, queue<int>& Q) {
        while (!Q.empty())
            Q.pop();
        int endNod = adiac.size() - 1;
        int s = 0;
        memset(&parent[0], 0xFF, parent.size() * sizeof(parent[0]));
        Q.push(0);
        parent[0] = -2;
        while (!Q.empty()) {
            int t = Q.front();
            Q.pop();
            for (auto i = adiac[t].begin(); i != adiac[t].end(); ++i) {
                if (parent[i->toNod] != -1 || i->capacity - i->flow == 0)
                    continue;
                if (i->toNod == endNod) {
                    int M = i->capacity - i->flow;
                    int curNod = t;
                    while (parent[curNod] != -2) {
                        int availableFlow = capToParent[curNod] - *flowToParent[curNod];
                        if (!availableFlow)
                            break;
                        if (availableFlow < M)
                            M = availableFlow;
                        curNod = parent[curNod];
                    }
                    if (parent[curNod] != -2)
                        continue;
 
                    i->flow += M;
                    i->dup->flow -= M;
                    curNod = t;
                    while (parent[curNod] != -2) {
                        *flowToParent[curNod] += M;
                        *flowToParentDup[curNod] -= M;
                        curNod = parent[curNod];
                    }
                    s += M;
                }
                else {
                    int curNod = i->toNod;
                    parent[curNod] = t;
                    capToParent[curNod] = i->capacity;
                    flowToParent[curNod] = &i->flow;
                    flowToParentDup[curNod] = &i->dup->flow;
                    Q.push(curNod);
                }
            }
        }
        return s;
    }
    int EdmondsKarp() {
        int s = 0;
        vector<int> parent(adiac.size());
        vector<int> capToParent(adiac.size());
        vector<int*> flowToParent(adiac.size());
        vector<int*> flowToParentDup(adiac.size());
        queue<int> Q;
        while (true) {
            int res = sendFlows(parent, capToParent, flowToParent, flowToParentDup, Q);
            if (!res)
                break;
            s += res;
        }
        return s;
    }
    void DFSnesaturat(int nod, vector<char>& visited) {
        visited[nod] = 1;
        for (auto i = adiac[nod].begin(); i != adiac[nod].end(); ++i)
        if (!visited[i->toNod] && !i->isSaturated())
            DFSnesaturat(i->toNod, visited);
    }
    void getCriticalEdges(vector<int>& sol) {
        EdmondsKarp();
        vector<char> reachableFromSource(adiac.size(), 0);
        DFSnesaturat(0, reachableFromSource);
        vector<char> reachableFromSink(adiac.size(), 0);
        DFSnesaturat(adiac.size() - 1, reachableFromSink);
        int n1, n2;
        for (auto i = adiac.begin(); i != adiac.end(); ++i)
        for (auto j = i->begin(); j != i->end(); ++j) {
            n1 = distance(adiac.begin(), i);
            n2 = j->toNod;
            if (j->ID >= 0 && j->isSaturated() && ((reachableFromSink[n1] && reachableFromSource[n2]) || (reachableFromSink[n2] && reachableFromSource[n1]))) {
                sol.push_back(j->ID);
                j->dup->ID = -1;
            }
        }
    }
};
 
int main() {
    assert(freopen(InFile, "r", stdin));
    assert(freopen(OtFile, "w", stdout));
    int N, M;
    scanf("%d%d", &N, &M);
    graph G(N);
    for (int i = 0; i < M; i++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        G.newEdge(a - 1, b - 1, c);
    }
    vector<int> sol;
    sol.reserve(M);
    G.getCriticalEdges(sol);
    printf("%d\n", sol.size());
    for (auto i = sol.begin(); i != sol.end(); ++i)
        printf("%d\n", (*i) + 1);
    return 0;
}