Cod sursa(job #2689637)

Utilizator Constantin.Dragancea Constantin Constantin. Data 21 decembrie 2020 18:22:14
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.14 kb
#include <bits/stdc++.h>
using namespace std;

struct Graph{
	int l, r, n, s, d;
	vector < vector <int> > graph;
	vector < vector <int> > cap, cost;
	vector <int> cost_dist, flux_dist, pr;
	queue <int> Q;
	priority_queue < pair <int, int> > S;
	vector <bool> vis;

	Graph(int _l, int _r): l(_l), r(_r), n(r + l + 2), s(0), d(n - 1), graph(n),
		cap(n, vector<int>(n)), cost(cap), cost_dist(n),
		flux_dist(n), pr(n), vis(n) {
			for (int i = 1; i <= l; ++i)
				AddEdge(0, i, 1, 0);

			for (int i = l + 1; i <= l + r; ++i)
				AddEdge(i, d, 1, 0);
		}

	void AddEdge(int a, int b, int cp, int cst){
		graph[a].push_back(b);
		graph[b].push_back(a);
		cap[a][b] += cp;
		cost[a][b] += cst;
		cost[b][a] -= cst;
	}

	void Bellman(){
		fill(cost_dist.begin(), cost_dist.end(), 1e9);
		fill(vis.begin(), vis.end(), 0);

		Q.push(s);
		cost_dist[s] = 0;
		vis[s] = 1;

		while (not Q.empty()){
			int node = Q.front();
			Q.pop();
			vis[node] = 0;

			int curr_cost = cost_dist[node];

			for (int nei: graph[node]){
				if (!cap[node][nei])
					continue;

				int new_dist = curr_cost + cost[node][nei];
				if (new_dist < cost_dist[nei]){
					cost_dist[nei] = new_dist;
					if (!vis[nei]){
						vis[nei] = 1;
						Q.push(nei);
					}
				}
			}
		}
	}

	pair <int, int> Dijkstra(){
		fill(flux_dist.begin(), flux_dist.end(), 1e9);
		vector <int> aux(n, 1e9);

		S.push({0, s});
		flux_dist[s] = 0;
		aux[s] = 0;

		while (not S.empty()){
			int curr_cost = -S.top().first;
			int node = S.top().second;
			S.pop();

			if (curr_cost != flux_dist[node])
				continue;

			for (int nei: graph[node]){
				if (!cap[node][nei])
					continue;
				int new_dist = curr_cost + cost[node][nei] + cost_dist[node] - cost_dist[nei];
				if (new_dist < flux_dist[nei]){
					flux_dist[nei] = new_dist;
					S.push({-flux_dist[nei], nei});
					pr[nei] = node;
					aux[nei] = aux[node] + cost[node][nei];
				}
			}
		}

		if (flux_dist[d] == 1e9)
			return {0, 0};

		int flow = 1e9;
		for (int node = d; node != s; node = pr[node])
			flow = min(flow, cap[pr[node]][node]);

		for (int node = d; node != s; node = pr[node]){
			cap[pr[node]][node] -= flow;
			cap[node][pr[node]] += flow;
		}

		cost_dist = aux;

		return {flow, cost_dist[d] * flow};
	}

	pair <int, int> MinCostMaxFlow(){
		Bellman();

		int maxFlow = 0, minCost = 0;
		while(1){
			auto lol = Dijkstra();
			if (lol.first == 0)
				break;

			maxFlow += lol.first;
			minCost += lol.second;
		}
		
		return {maxFlow, minCost};
	}

	vector <int> getUsedEdges(vector <pair <int, int> >& edges){
		vector <int> ans;
		
		for (int i = 0; i < (int) edges.size(); ++i){
			int a = edges[i].first;
			int b = edges[i].second;
			if (!cap[a][b])
				ans.push_back(i + 1);
		}

		return ans;
	}
};



int main(){
	ifstream cin("cmcm.in");
	ofstream cout("cmcm.out");

	int l, r, m;
	cin >> l >> r >> m;

	Graph G(l, r);

	vector < pair <int, int> > edges;
	for (int i = 1; i <= m; ++i){
		int a, b, z;
		cin >> a >> b >> z;
		G.AddEdge(a, l + b, 1, z);
		edges.push_back({a, l + b});
	}

	auto ans = G.MinCostMaxFlow();
	cout << ans.first << ' ' << ans.second << '\n';
	
	auto vec = G.getUsedEdges(edges);
	for (int it : vec)
		cout << it << ' ';

	return 0;
}