Cod sursa(job #2585881)

Utilizator CyborgSquirrelJardan Andrei CyborgSquirrel Data 19 martie 2020 14:54:16
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.63 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <bitset>
#include <set>

using namespace std;

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

typedef long long lint;

const int INF = 0x3f3f3f3f;
struct nod{
	int a, v = INF;
	bool operator<(const nod &rhs)const{
		if(v != rhs.v){
			return v < rhs.v;
		}else{
			return a < rhs.a;
		}
	}
};

int n, m, s, d;
int cap[410][410], flo[410][410];
int rcst[410][410];

vector<int> gra[410];

void read(){
	fin >> n >> m >> s >> d;
	for(int i = 0; i < m; ++i){
		int a, b;
		fin >> a >> b;
		fin >> cap[a][b] >> rcst[a][b];
		rcst[b][a] = -rcst[a][b];
		gra[a].push_back(b);
		gra[b].push_back(a);
	}
}

bool bfs(){
	static queue<int> qu;
	static bitset<410> vi;
	
	vi.reset();
	qu.push(s);
	vi[s] = true;
	while(!qu.empty()){
		int a = qu.front();
		qu.pop();
		for(auto b : gra[a]){
			if(!vi[b] && flo[a][b] < cap[a][b]){
				vi[b] = true;
				if(b != d)qu.push(b);
			}
		}
	}
	return vi[d];
}

int dist[410];
int rdist[410];

void nuke(){
	for(int i = 1; i <= n; ++i){
		dist[i] = INF;
	}
	dist[s] = 0;
}

void bellman(){
	static queue<int> qu;
	static bitset<410> vi;
	
	nuke();
	qu.push(s);
	vi[s] = true;
	while(!qu.empty()){
		int a = qu.front();
		qu.pop();
		vi[a] = false;
		for(auto b : gra[a]){
			int v = dist[a]+rcst[a][b];
			if(v < dist[b] && cap[a][b] != 0){
				dist[b] = v;
				if(!vi[b]){
					qu.push(b);
					vi[b] = true;
				}
			}
		}
	}
}

int cst[410][410];
void postbellman(){
	for(int i = 1; i <= n; ++i){
		for(int j = 1; j <= n; ++j){
			cst[i][j] = dist[i] - dist[j] + rcst[i][j];
		}
	}
}

set<nod> pq;
int dad[410];
void dijkstra(){
	nuke();
	pq.insert({s, 0});
	rdist[s] = 0;
	while(!pq.empty()){
		int a = pq.begin()->a;
		pq.erase(pq.begin());
		for(auto b : gra[a]){
			int v = dist[a] + cst[a][b];
			if(v < dist[b] && flo[a][b] < cap[a][b]){
				dad[b] = a;
				if(dist[b] != INF){
					pq.erase({b, dist[b]});
				}
				dist[b] = v;
				rdist[b] = rdist[a]+rcst[a][b];
				pq.insert({b, dist[b]});
			}
		}
	}
}

lint updateflow(){
	int fmin = INF;
	for(int x = d; x != s; x = dad[x]){
		fmin = min(fmin, cap[dad[x]][x] - flo[dad[x]][x]);
	}
	if(fmin != 0){
		for(int x = d; x != s; x = dad[x]){
			flo[dad[x]][x] += fmin;
			flo[x][dad[x]] -= fmin;
		}
		return fmin*rdist[d];
	}
	return 0;
}

lint ans = 0;
void maxflow(){
	while(bfs()){
		dijkstra();
		ans += updateflow();
	}
}

void solve(){
	bellman();
	postbellman();
	maxflow();
}

int main(){
	read();
	solve();
	fout << ans;
	return 0;
}