Cod sursa(job #935144)

Utilizator okros_alexandruOkros Alexandru okros_alexandru Data 1 aprilie 2013 20:39:25
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.53 kb
#include <fstream>
#include <vector>
#include <queue>
#define nmax 360
#define oo (1<<30)
#define Neighbor Graph[Node][i]
using namespace std;

vector <int> Graph[nmax];
int N, M, Source, Sink, CostMaxFlow, Distance[nmax];
int Capacity[nmax][nmax], Cost[nmax][nmax], Father[nmax];
bool inQueue[nmax];

class heap {
	
	#define hmax nmax;
	#define father(node) (node>>1)
	#define leftSon(node) (node<<1)
	#define rightSon(node) ((node<<1)|1)
	#define compare(a, b) ( Distance[H[a]] < Distance[H[b]] )
	#define compareMin(a, b) compare(a, b)
	#define comapreMax(a, b) compare(b, a)
	
	public:
		int Top,H[nmax],Index[nmax];
		
	public:
		
		heap() {
			
			Top = 0;
			
			}
		
		void precolate(int Node) {
			
			while( Node > 1 && compareMin(Node, father(Node)) ) {
				
				swap(H[Node], H[father(Node)]);
				swap(Index[H[Node]], Index[H[father(Node)]]);
				Node = father(Node);
				
				}
			
		}
		
		void sift(int Node) {
			
			int Son;
			
			do {
				
				Son = 0;
				
				if( leftSon(Node) <= this -> size() ) {
					
					Son = leftSon(Node);
					
					if( rightSon(Node) <= this -> size() && compareMin(rightSon(Node), Son) )
						Son = rightSon(Node);
					
					if( compareMin(Node, Son) )
						Son = 0;
					
					}
				
				if( Son ) {
					
					swap(H[Node], H[Son]);
					swap(Index[H[Node]], Index[H[Son]]);
					Node = Son;
					
					}
				
			} while( Son );
			
		}
		
		void push(int Node, int Value) {
			
			H[ ++Top ] = Node;
			Index[Node] = Top;
			Distance[Node] = Value;
			this -> precolate(Top);
			
			}
		
		void pop() {
			
			H[1] = H[ Top-- ];
			this -> sift(1);
			
			}
		
		void update(int Node, int Value) {
			
			int Aux = Distance[Node];
			
			Distance[Node] = Value;
			
			if( Aux > Distance[Node] )
				this -> precolate( Index[Node] );
			else
				this -> sift( Index[Node] );
			
			}
		
		int size() {
			
			return Top;
			
			}
		
		bool empty() {
			
			return ( Top == 0);
			
			}
		
		int top() {
			
			return H[1];
			
			}
	
};

void InitialiseDijkstra() {
	
	int i, Node;
	
	for(Node = 1; Node <= N; Node++)
		for(i = 0; i < Graph[Node].size(); i++)
			if( Distance[Node] != oo && Distance[Neighbor] != oo )
				Cost[Node][Neighbor] += Distance[Node] - Distance[Neighbor];
	
}
bool Dijkstra(int Source, int Sink) {
	
	int i, Node;
	heap Heap;
	
	InitialiseDijkstra();
	
	for(Node = 1; Node <= N; Node++)
		Heap.push(Node, oo);
	
	Heap.update(Source, 0);
	
	while( !Heap.empty() ) {
		
		Node = Heap.top();
		Heap.pop();
		
		for(i = 0; i < Graph[Node].size(); i++)
			if( Capacity[Node][Neighbor] > 0 && Distance[Neighbor] > Distance[Node] + Cost[Node][Neighbor] ) {
				
				Father[Neighbor] = Node;
				Heap.update(Neighbor, Distance[Node] + Cost[Node][Neighbor] );
				
				}
			
		}
	
	return ( Distance[Sink] != oo );
	
}
int BellmanFord(int Source, int Sink) {
	
	int i, Node;
	queue <int> Queue;
	
	for(i = 1; i <= N; i++)
		Distance[i] = oo;
	
	Queue.push(Source);
	Distance[Source] = 0;
	
	while(!Queue.empty()) {
		
		Node = Queue.front();
		Queue.pop();
		inQueue[Node] = false;
		
		for(i = 0; i < Graph[Node].size(); i++)
			if( Capacity[Node][Neighbor] > 0 && Distance[Neighbor] > Distance[Node] + Cost[Node][Neighbor] ) {
				
				Distance[Neighbor] = Distance[Node] + Cost[Node][Neighbor];
				
				if( !inQueue[Neighbor] ) {
					
					Queue.push(Neighbor);
					inQueue[Neighbor] = true;
					
					}
			
			}
		
		}
	
	return Distance[Sink];
	
}
void Solve() {
	
	int i, Sum, maxFlow, Node;
	
	Sum = BellmanFord(Source, Sink);
	
	while( Dijkstra(Source, Sink) ) {
		
		maxFlow = oo;
		
		for(Node = Sink; Node != Source; Node = Father[Node])
			maxFlow = min(maxFlow, Capacity[Father[Node]][Node]);
		
		for(Node = Sink; Node != Source; Node = Father[Node]) {
			
			Capacity[Father[Node]][Node] -= maxFlow;
			Capacity[Node][Father[Node]] += maxFlow;
			
			}
		
		Sum += Distance[Sink];
		
		CostMaxFlow += Sum * maxFlow;
		
		}
	
}
void Read() {
	
	int i, x, y, capacity, cost;
	ifstream in("fmcm.in");
	in>>N>>M>>Source>>Sink;
	
	for(i = 1; i <= M; i++) {
		
		in>>x>>y>>capacity>>cost;
		Graph[x].push_back(y);
		Graph[y].push_back(x);
		Cost[x][y] = cost;
		Cost[y][x] = -cost;
		Capacity[x][y] = capacity;
		
		}
	
	in.close();

}
void Write() {
	
	ofstream out("fmcm.out");
	out<<CostMaxFlow<<'\n';
	out.close();
	
}
int main() {
	
	Read();
	Solve();
	Write();
	
	return 0;
	
}