Cod sursa(job #2937367)

Utilizator andrei_C1Andrei Chertes andrei_C1 Data 10 noiembrie 2022 11:17:52
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.65 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

const int INF = 1e9;

int T;
int N, M;
int source, destination;

struct Edge {
	int u, v, cap, cost, flow;
};

vector<Edge> edges;
vector<vector<int>> adj;
vector<int> potential;
vector<int> distHelper, dist;
vector<int> parent;

void addEdge(int u, int v, int cap, int cost, int flow = 0) {
	int m = edges.size();
	edges.push_back({u, v, cap, cost, flow});
	edges.push_back({v, u, 0, -cost, 0});

	adj[u].push_back(m);
	adj[v].push_back(m + 1);
}

void bf() {
	queue<int> q;
	vector<bool> inQ(N + 1);
	dist = vector<int> (N + 1, INF);
	dist[source] = 0;

	q.push(source);
	inQ[source] = 1;

	while(!q.empty()) {
		int u = q.front();
		q.pop();
		inQ[u] = 0;

		for(const auto &it: adj[u]) {
			int v = edges[it].v;
			int cap = edges[it].cap;
			int cost = edges[it].cost;

			if(cap > 0 && dist[v] > dist[u] + cost) {
				dist[v] = dist[u] + cost;

				if(!inQ[v]) {
					q.push(v);
					inQ[v] = 1;
				}
			}
		}
	}
}

struct compare {
	bool operator () (const int &u, const int &v) {
		return distHelper[u] > distHelper[v];
	}
};

bool dij() {
	priority_queue<int, vector<int>, compare> pq;
	vector<bool> inQ(N + 1);
	parent = vector<int> (N + 1);
	potential = dist;
	dist = distHelper = vector<int> (N + 1, INF);
	dist[source] = distHelper[source] = 0;

	pq.push(source);
	inQ[source] = 1;

	while(!pq.empty()) {
		int u = pq.top();
		pq.pop();
		inQ[u] = 0;

		for(const auto &it: adj[u]) {
			int v = edges[it].v;
			int cap = edges[it].cap;
			int cost = edges[it].cost;
			int flow = edges[it].flow;

			if(cap - flow > 0 && distHelper[v] + potential[v] > distHelper[u] + potential[u] + cost) {
				distHelper[v] = distHelper[u] + potential[u] + cost - potential[v];
				dist[v] = dist[u] + cost;
				parent[v] = it;

				if(!inQ[v]) {
					pq.push(v);
					inQ[v] = 1;
				}
			}
		}
	}

	return distHelper[destination] != INF;
}

void solve() {
	fin >> N >> M >> source >> destination;

	edges = vector<Edge> (0);
	adj = vector<vector<int>> (N + 1);

	for(int i = 1; i <= M; i++) {
		int u, v, c, z;
		fin >> u >> v >> c >> z;
		addEdge(u, v, c, z);
	}

	bf();

	int maxFlow = 0, minCost = 0;

	while(dij()) {
		int flow = INF, cost = 0;

		for(int u = destination; u != source; u = edges[parent[u]].u) {
			flow = min(flow, edges[parent[u]].cap - edges[parent[u]].flow);
			cost += edges[parent[u]].cost;
		}

		maxFlow += flow;
		minCost += cost * flow;

		for(int u = destination; u != source; u = edges[parent[u]].u) {
			edges[parent[u]].flow += flow;
			edges[parent[u] ^ 1].flow -= flow;
		}
	}

	fout << minCost << '\n';
}

int main() {
	ios_base :: sync_with_stdio(false);

	solve();
	return 0;
}