Cod sursa(job #1464513)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 23 iulie 2015 18:29:28
Problema Critice Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.44 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, capacity, *flow;
    edge(int N, int p, int* f) {
        toNod = N;
        capacity = p;
        flow = f;
    }
    friend class graph;
};

class edge2 {
private:
	int n1, n2, *flow, cap;
	edge2(int N1, int N2, int* FLOW, int CAP) {
		n1 = N1; n2 = N2; flow = FLOW; cap = CAP;
	}
	friend class graph;
};
 
class graph {
private:
    vector< list<edge> > adiac;
	vector< edge2 > edgeTracker;
public:
    graph(int N, int M) {
		adiac.resize(N + 1);
		edgeTracker.reserve(M + 2);
	}
    void addEdge(int n1, int n2, int cap) {
        int* f = new int(0);
        adiac[n1].push_back(edge(n2, cap, f));
		adiac[n2].push_back(edge(n1, cap, f));
		adiac[n1].push_back(edge(-n2, cap, f));
        adiac[n2].push_back(edge(-n1, cap, f));
		edgeTracker.push_back(edge2(n1, n2, f, cap));
    }
    int size() { return adiac.size() - 1; }
    int sendFlows(int nod, int endNod, vector<int> &parent, vector<int*> &flowArcToParent, vector<int> &capArcToParent, vector<char> &isForwardArc, queue<int>& Q) {
        int s = 0;
        memset(&parent[0], 0xFF, parent.size()*sizeof(parent[0]));
        while (!Q.empty())
            Q.pop();
        Q.push(nod);
        parent[nod] = 0;
        while (!Q.empty()) {
            int t = Q.front();
            Q.pop();
            for (auto i = adiac[t].begin(); i != adiac[t].end(); ++i) {
				if (t == nod && i->toNod < 0)
					continue;
                int curnod = i->toNod > 0 ? i->toNod : -(i->toNod);
                if (curnod == endNod) {
					if (i->toNod < 0)
						continue;
                    int MF = i->capacity - *i->flow;
					if (!MF)
						continue;
                    int aux = t;
                    while (parent[aux]) {
                        int availableFlow = isForwardArc[aux] ? capArcToParent[aux] - *flowArcToParent[aux] : *flowArcToParent[aux];
                        if (!availableFlow)
                            break;
                        if (availableFlow < MF)
                            MF = availableFlow;
                        aux = parent[aux];
                    }
                    if (!parent[aux]) {
                        if (i->toNod > 0)
                            *i->flow += MF;
                        else
                            *i->flow -= MF;
                        aux = t;
                        while (parent[aux]) {
                            if (isForwardArc[aux])
                                *flowArcToParent[aux] += MF;
                            else
                                *flowArcToParent[aux] -= MF;
                            aux = parent[aux];
                        }
                        s += MF;
						return s;
                    }
                }
                else if (parent[curnod] == -1) {
                    int availableFlow = i->toNod > 0 ? i->capacity - *i->flow : *i->flow;
                    if (availableFlow) {
                        Q.push(curnod);
                        parent[curnod] = t;
                        flowArcToParent[curnod] = i->flow;
                        capArcToParent[curnod] = i->capacity;
                        if (i->toNod > 0)
                            isForwardArc[curnod] = 1;
                        else
                            isForwardArc[curnod] = 0;
                    }
                }
            }
        }
        return s;
    }
    int EdmondsKarp(int source, int sink) {
        int s = 0;
        vector<int> parent(size() + 1), caps(size() + 1);
        vector<int*> flows(size() + 1);
        vector<char> isForward(size() + 1);
        queue<int> Q;
        while (true) {
            int flowSent = sendFlows(source, sink, parent, flows, caps, isForward, Q);
            if (!flowSent)
                break;
            s += flowSent;
            //fprintf(stderr, "%d\n", s);
        }
        return s;
    }
	void unsaturatedDFS(int nod, vector<char> &visited) {
		visited[nod] = 1;
		for (auto i = adiac[nod].begin(); i != adiac[nod].end(); ++i)
		if (i->toNod > 0 && !visited[i->toNod] && *i->flow != i->capacity)
			unsaturatedDFS(i->toNod, visited);
	}
	void criticalEdges() {
		int N = size();
		EdmondsKarp(1, N);
		vector<char> visitedFromSource(N + 1, 0);
		unsaturatedDFS(1, visitedFromSource);
		vector<char> visitedFromSink(N + 1, 0);
		unsaturatedDFS(N, visitedFromSink);
		list<int> sol;
		for (auto i = edgeTracker.begin(); i != edgeTracker.end(); ++i)
		if (*i->flow == i->cap && ((visitedFromSource[i->n1] && visitedFromSink[i->n2]) || (visitedFromSource[i->n2] && visitedFromSink[i->n1])))
			sol.push_back(distance(edgeTracker.begin(), i) + 1);
		printf("%d\n", sol.size());
		for (auto i = sol.begin(); i != sol.end(); ++i)
			printf("%d\n", *i);
	}
};
 
int main() {
    assert(freopen(InFile, "r", stdin));
    assert(freopen(OtFile, "w", stdout));
    int N, M;
    scanf("%d%d", &N, &M);
    graph* G = new graph(N, M);
    for (int i = 0; i < M; i++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        G->addEdge(a, b, c);
    }
	G->criticalEdges();
    return 0;
}