Cod sursa(job #815532)

Utilizator ahmed.abdraboahmed.abdrabo ahmed.abdrabo Data 17 noiembrie 2012 10:12:31
Problema Cuplaj maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.06 kb
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <queue>
#include <set>
#include <vector>

using namespace std;

inline int next_int() {
	int d;
	scanf("%d", &d);
	return d;
}

const int INF = 1e9;

struct MinCostMaxFlow {
	int V, E, min_cost, max_flow, path_cost, path_flow, where;
	vector<int> from, to, capacity, cost;
	MinCostMaxFlow(int n) {
		V = n, E = 0, min_cost = 0, max_flow = 0;
		from.clear(), to.clear(), capacity.clear(), cost.clear();
	}
	void add_edge(int a, int b, int c, int d) {
		E++, from.push_back(a), to.push_back(b), capacity.push_back(c), cost.push_back(+d);
		E++, from.push_back(b), to.push_back(a), capacity.push_back(0), cost.push_back(-d);
	}
	void run(const int source, const int sink) {
		vector<int> e_begin(V, -1), e_next(E);
		for (int e = 0; e < E; e++) {
			e_next[e] = e_begin[from[e]];
			e_begin[from[e]] = e;
		}
		vector<int> dist(V, INF);
		dist[source] = 0;
		for (int v = 0; v < V; v++) {
			int done = 1;
			for (int e = 0; e < E; e++) {
				int a = from[e], b = to[e], c = capacity[e], d = cost[e];
				if (dist[a] < INF && c > 0 && dist[a] + d < dist[b]) {
					dist[b] = dist[a] + d;
					done = 0;
				}
			}
			if (done) {
				break;
			}
		}
		path_cost = dist[sink];
		while (true) {
			for (int e = 0; e < E; e++) {
				int a = from[e], b = to[e];
				if (dist[a] < INF && dist[b] < INF) {
					cost[e] += dist[a] - dist[b];
				}
			}
			vector<int> prev(V, -1), seen(V, false);
			dist.assign(V, INF);
			dist[source] = 0;
			priority_queue<pair<int, int> , vector<pair<int, int> > , greater<pair<int, int> > > Q;
			Q.push(make_pair(0, source));
			while (!Q.empty()) {
				int current_dist = Q.top().first;
				int current_where = Q.top().second;
				Q.pop();
				if (seen[current_where] == false) {
					seen[current_where] = true;
					for (int e = e_begin[current_where]; e != -1; e = e_next[e]) {
						int b = to[e], c = capacity[e], d = cost[e];
						if (c > 0 && current_dist + d < dist[b]) {
							Q.push(make_pair(current_dist + d, b));
							dist[b] = current_dist + d;
							prev[b] = e;
						}
					}
				}
			}
			if (dist[sink] == INF) {
				break;
			}
			path_flow = 1;
			for (where = sink; where != source; where = from[prev[where]]) {
				capacity[prev[where] ^ 0]--;
				capacity[prev[where] ^ 1]++;
			}
			path_cost += dist[sink];
			min_cost += path_flow * path_cost;
			max_flow += path_flow;
		}
	}
};

int main() {
	int c1 = next_int();
	int c2 = next_int();
	int n = c1 + c2 + 2;
	int source = c1 + c2;
	int sink = c1 + c2 + 1;
	MinCostMaxFlow mcmf(n);
	for (int i = 0; i < c1; i++) {
		mcmf.add_edge(source, i, 1, 0);
	}
	for (int i = 0; i < c2; i++) {
		mcmf.add_edge(c1 + i, sink, 1, 0);
	}
	int m = next_int();
	vector<int> edges;
	for (int i = 0; i < m; i++) {
		int x = next_int();
		int y = next_int();
		int z = next_int();
		edges.push_back(mcmf.E);
		mcmf.add_edge(x - 1, c1 + y - 1, 1, z);
	}
	mcmf.run(source, sink);
	printf("%d\n", mcmf.max_flow);
	printf("%d\n", mcmf.min_cost);
	for (int i = 0; i < m; i++) {
		if (mcmf.capacity[edges[i]] == 0) {
			printf("%d ", i + 1);
		}
	}
	return 0;
}