Cod sursa(job #2958810)

Utilizator ViAlexVisan Alexandru ViAlex Data 28 decembrie 2022 14:10:36
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.5 kb
#include<iostream>
#include<deque>
#include<algorithm>
#include<vector>
#include<fstream>
#include<queue>
using namespace std;

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

const int mx = 400;
const int inf = 1e9;

struct node{
	int index,distance;
};

struct flow_result {
	int flow, cost;
};

struct compare{
	bool operator ()(const node&a, const node&b){
		return a.distance>b.distance;
	}
};

int n,m,s,t;

int capacity[mx][mx];

// cost[i][j] - the cost of the edge (i,j)
int cost[mx][mx];

// dist[i] = the minimum distance from s to i
int old_dist[mx];
int dist[mx];
int parent[mx];

bool in_queue[mx];

vector<int> g[mx];


void read(){
	in>>n>>m>>s>>t;
	int a,b,c,d;
	for(int i=0;i<m;i++){
		in>>a>>b>>c>>d;

		cost[a][b] = d;
		cost[b][a] = -d;

		capacity[a][b] = c;
		capacity[b][a] = 0;

		g[a].push_back(b);
		g[b].push_back(a);
	}
}

void bf(){
	for(int i=1;i<=n;i++){
		old_dist[i] = inf;
	}	

	old_dist[s] = 0;
	queue<int> q;
	q.push(s);
	in_queue[s] = true;

	while(!q.empty()){
		int here = q.front();
		q.pop();
		in_queue[here] = false;

		for(int k:g[here]){
			if(capacity[here][k] == 0)
				continue;
			if(old_dist[here] + cost[here][k] < old_dist[k]){
				old_dist[k] = old_dist[here] + cost[here][k];
				if(!in_queue[k]){
					q.push(k);
					in_queue[k] = true;
				}
			}
		}
	}
}

flow_result flow(){
	for(int i=1;i<=n;i++){
		parent[i] = -1;
		dist[i] = inf;
	}

	priority_queue<node,vector<node>,compare> q;	
	q.push({s,0});
	dist[s] = 0;
	parent[s] = 0;

	while(!q.empty()){
		node here = q.top();
		q.pop();
		if(here.distance != dist[here.index])
			continue;
		for(int k:g[here.index]){
			if(capacity[here.index][k] == 0)
				continue;
			
			int distance = old_dist[here.index] + cost[here.index][k] - old_dist[k];
			int new_dist = here.distance + distance;
			if(new_dist < dist[k]){
				dist[k] = new_dist;
				parent[k] = here.index;
				q.push({k,new_dist});
			}
		}
	}
	int c= 0;
	int flow = inf;

	if(parent[t] == -1)
		return {0,0};

	int now = t;
	while(now!=s){
		flow = min(flow, capacity[parent[now]][now]);
		c += cost[parent[now]][now]; 
		now = parent[now];
	}
	now = t;
	while(now!=s){
		capacity[parent[now]][now] -= flow;
		capacity[now][parent[now]] += flow;
		now = parent[now];
	}

	for(int i=1;i<=n;i++){
		old_dist[i] = dist[i];
	}
	return {flow, c*flow};
}

void solve(){
	bf();
	flow_result current_flow;
	int total_cost = 0;
	do{
		current_flow = flow();
		total_cost +=current_flow.cost;
	}
	while(current_flow.flow);
	out<<total_cost<<endl;
}

int main(){
	read();
	solve();

	return 0;
}