Cod sursa(job #1465425)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 27 iulie 2015 12:51:04
Problema Critice Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.12 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;
}