Cod sursa(job #1466726)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 30 iulie 2015 00:00:10
Problema Critice Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.65 kb
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <queue>
#include <cstring>
using namespace std;

#define ProblemName "critice"

#define MCONCAT(A, B) A B
#ifdef ProblemName
#define InFile MCONCAT(ProblemName, ".in")
#define OuFile MCONCAT(ProblemName, ".out")
#else
#define InFile "fis.in"
#define OuFile "fis.out"
#endif

#define MAXN 1010

int flow[MAXN][MAXN];
int capacity[MAXN][MAXN];

bool isSaturated(int n1, int n2) {
	if (capacity[n1][n2] - flow[n1][n2] == 0 || capacity[n2][n1] - flow[n2][n1] == 0)
		return true;
	return false;
}

class graph {
private:
	vector< list<int> > adiac;
	vector< pair<int, int> > edgeTracker;
public:
	graph(int N, int M) {
		adiac.resize(N);
		edgeTracker.resize(M);
	}
	void newEdge(int n1, int n2, int c, int enr) {
		edgeTracker[enr].first = n1; edgeTracker[enr].second = n2;
		adiac[n1].push_back(n2);
		adiac[n2].push_back(n1);
		flow[n1][n2] = flow[n2][n1] = 0;
		capacity[n1][n2] = capacity[n2][n1] = c;
	}
	
	int sendFlows(vector<char>& visited, vector<int>& parent, queue<int>& Q) {
		memset(&visited[0], 0, sizeof(visited[0]) * visited.size());
		int endNod = adiac.size() - 1;
		int s = 0;
		while (!Q.empty())
			Q.pop();
		Q.push(0);
		parent[0] = -1; visited[0] = 1;
		while (!Q.empty()) {
			int t = Q.front();
			Q.pop();
			for (auto i = adiac[t].begin(); i != adiac[t].end(); ++i) {
				if (visited[*i] || capacity[t][*i] - flow[t][*i] == 0)
					continue;
				if (*i == endNod) {
					int M = capacity[t][*i] - flow[t][*i];
					int aux = t;
					while (parent[aux] != -1) {
						int availableFlow = capacity[parent[aux]][aux] - flow[parent[aux]][aux];
						if (!availableFlow)
							break;
						M = availableFlow < M ? availableFlow : M;
						aux = parent[aux];
					}
					if (parent[aux] != -1 || !M)
						continue;
					flow[t][endNod] += M;
					flow[endNod][t] -= M;
					aux = t;
					while (parent[aux] != -1) {
						flow[parent[aux]][aux] += M;
						flow[aux][parent[aux]] -= M;
						aux = parent[aux];
					}
					s += M;
				}
				else {
					visited[*i] = 1;
					parent[*i] = t;
					Q.push(*i);
				}
			}
		}
		return s;
	}
	int EdmondsKarp() {
		int s = 0;
		vector<char> visited(adiac.size());
		vector<int> parent(adiac.size());
		queue<int> Q;
		while (true) {
			int sentFlow = sendFlows(visited, parent, Q);
			if (!sentFlow)
				break;
			s += sentFlow;
		}
		return s;
	}
	void DFSnesaturat(int nod, int endNod, vector<char>& visited) {
		visited[nod] = 1;
		if (nod == endNod)
			return;
		for (auto i = adiac[nod].begin(); i != adiac[nod].end(); ++i)
		if (!visited[*i] && !isSaturated(nod, *i))
			DFSnesaturat(*i, endNod, visited);
	}
	void getCriticalEdges(vector<int>& sol) {
		EdmondsKarp();
		int N = adiac.size();
		vector<char> fromSource(N, 0);
		DFSnesaturat(0, N - 1, fromSource);
		vector<char> fromSink(N, 0);
		DFSnesaturat(N - 1, 0, fromSink);
		for (unsigned int i = 0; i < edgeTracker.size(); i++) {
			int n1 = edgeTracker[i].first, n2 = edgeTracker[i].second;
			if (isSaturated(n1, n2) && ((fromSink[n1] && fromSource[n2]) || (fromSink[n2] && fromSource[n1])))
				sol.push_back(i);
		}
	}
};

int main() {
	assert(freopen(InFile, "r", stdin));
	assert(freopen(OuFile, "w", stdout));
	int N, M;
	scanf("%d%d", &N, &M);
	graph G(N, M);
	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, i);
	}
	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;
}