Cod sursa(job #2689619)

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

const int MAX = 2000000000;
const int N = 510;

int n, m, s, d;
int cost[N][N], cap[N][N], old_dist[N], dist[N], pr[N];
int aux[N];
bool vis[N];

vector <int> graph[N];
queue <int> Q;
priority_queue < pair <int, int> > S;

class InParser{
	private:
		FILE *fin;
		char *buff;
		int sp;

		char read_ch(){
			++sp;
			if (sp == 4096){
				sp = 0;
				fread(buff, 1, 4096, fin);
			}
			return buff[sp];
		}

	public:
		InParser(const char* nume){
			fin = fopen(nume, "r");
			buff = new char[4096]();
			sp = 4095;
		}

		InParser& operator>> (int &n){
			char c;
			while (!isdigit(c = read_ch()) && c != '-');
			
			int sgn = 1;
			if (c == '-'){
				n = 0;
				sgn = -1;
			}
			else{
				n = c - '0';
			}

			while (isdigit(c = read_ch())){
				n = n * 10 + c - '0';
			}
			n *= sgn;

			return *this;
		}
};

inline void Bellman(){
	int i, node, new_dist;
	for (i = 1; i <= n; ++i)
		old_dist[i] = MAX;
	memset(vis, 0, sizeof(vis));

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

	while(not Q.empty()){
		node = Q.front();
		Q.pop();

		for (int nei : graph[node]){
			if (!cap[node][nei])
				continue;
			
			new_dist = old_dist[node] + cost[node][nei];
			if (new_dist < old_dist[nei]){
				old_dist[nei] = new_dist;
				if (!vis[nei]){
					Q.push(nei);
					vis[nei] = 1;
				}
			}
		}
		vis[node] = 0;
	}
}

inline int Dijkstra(){
	int i, node, new_dist, curr_cost;
	for (i = 1; i <= n; ++i){
		pr[i] = -1;
		dist[i] = MAX;
		vis[i] = 0;
		aux[i] = MAX;
	}
	
	S.push({0, s});
	dist[s] = 0;
	aux[s] = 0;

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

		if (vis[node])
			continue;
		vis[node] = 1;

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

			new_dist = curr_cost + cost[node][nei] + old_dist[node] - old_dist[nei];
			if (new_dist < dist[nei]){
				dist[nei] = new_dist;
				aux[nei] = aux[node] + cost[node][nei];
				pr[nei] = node;
				S.push({-new_dist, nei});
			}
		}
	}

	for (i = 1; i <= n; ++i){
		old_dist[i] = aux[i];
	}

	if (dist[d] == MAX)
		return 0;
	
	int flow = 1e9, path_cost = 0;
	for (node = d; node != s; node = pr[node])
		flow = min(flow, cap[pr[node]][node]);
	
	for (node = d; node != s; node = pr[node]){
		cap[pr[node]][node] -= flow;
		cap[node][pr[node]] += flow;
		path_cost += cost[pr[node]][node];
	}

	return flow * path_cost;
}

int main(){
	InParser cin("fmcm.in");
	ofstream cout("fmcm.out");
	
	int i, a, b, c, z;
	cin >> n >> m >> s >> d;
	for (i = 1; i <= m; ++i){
		cin >> a >> b >> c >> z;
		graph[a].push_back(b);
		graph[b].push_back(a);
		cost[a][b] = z;
		cost[b][a] = -z;
		cap[a][b] = c;
	}

	Bellman();

	int ans = 0, path_cost = 0;
	do{
		path_cost = Dijkstra();
		ans += path_cost;
	} while(path_cost);

	cout << ans << '\n';

	return 0;
}