Cod sursa(job #615851)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 11 octombrie 2011 05:47:32
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 7.99 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <bitset>
#include <cstring>
#include <cassert>

#define MAXN 355
#define INF 0x3f3f3f3f

#define minimum(a,b)	\
({						\
	typeof(a) _a = a;	\
	typeof(b) _b = b;	\
	_a<=_b?_a:_b;		\
})

using namespace std;

typedef unsigned short uint16;

class CHeap
{
private:
	uint16 size;
	vector<uint16> vIndexes;
	vector<pair<int,uint16> > vHeap;
	
	inline void swap(const uint16 first, const uint16 second)
	{
		vIndexes[vHeap[first].second]=second;
		vIndexes[vHeap[second].second]=first;
		pair<int,uint16> aux;
		aux=vHeap[first];
		vHeap[first]=vHeap[second];
		vHeap[second]=aux;
	}
	
	void siftUp(int index)
	{
		int parent=(index-1-!(index%2))>>1;
		while(parent>=0 && vHeap[index].first<vHeap[parent].first)
		{
			swap(parent,index);
			index=parent;
			parent=(index-1-!(index%2))>>1;
		}
	}
	
	void siftDown(int index)
	{
		int child1,child2;
		bool ord=true;
		child1=(index<<1)+1;
		child2=(index+1)<<1;
		while(ord && child1<size)
		{
			ord=false;
			if(child2<size)
			{
				if(vHeap[child1].first<vHeap[child2].first)
				{
					if(vHeap[child1]<vHeap[index])
					{
						swap(child1,index);
						index=child1;
						ord=true;
					}
				}
				else if(vHeap[child2].first<vHeap[index].first)
				{
					swap(child2,index);
					index=child2;
					ord=true;
				}
			}
			else if(vHeap[child1].first<vHeap[index].first)
			{
				swap(child1,index);
				index=child1;
				ord=true;
			}
			child1=(index<<1)+1;
			child2=(index+1)<<1;
		}
	}
public:

	CHeap() : size(0)
	{}

	void insert(const pair<int,uint16>& val)
	{
		vHeap.push_back(val);
		vIndexes.push_back(size++);
		siftUp(size-1);
	}
	
	inline void modify(const int pos, const pair<int,uint16>& val)
	{
		vHeap[pos]=val;
		siftUp(pos);
	}
	
	inline void remove(const int pos)
	{
		swap(pos,--size);
		vHeap.pop_back();
		siftDown(pos);
	}
	
	inline const pair<int,uint16>& getElement(const int pos) const
	{
		return vHeap[pos];
	}
	
	inline int getPos(const int index) const
	{
		return vIndexes[index];
	}
	
	inline bool empty() const
	{
		return (size==0);
	}
	
	void print()
	{
		for(unsigned int i=0; i<vHeap.size(); ++i)
		{
			cout<<"("<<vHeap[i].first<<" "<<vHeap[i].second+1<<") ";
		}
		cout<<endl;
		for(unsigned int i=0; i<vIndexes.size(); ++i)
		{
			cout<<"("<< vIndexes[i] <<") ";
		}
		cout<<endl;
	}
};

struct Edge
{
	Edge() :
		node(0),
		cost(0)
	{}
	Edge(const short n, const short c) :
		node(n),
		cost(c)
	{}
	
	short node;
	short cost;
};

typedef vector<vector<Edge> > Graph;

bool BellmanFord(const Graph &graph,
				 int **capacity,
				 int **flow,
				 const int n,
				 const uint16 s,
				 int *dist // out
				)
{
	queue<uint16> Q;
	uint16 count[MAXN]={0};
	bool neg_cycle=false;
	bitset<MAXN> inQ;
	
	memset(dist,0x3f,n*sizeof(int));
	dist[s]=0;

	Q.push(s);
	inQ[s]=true;

	while(!Q.empty() && !neg_cycle)
	//for (int i=0; i<n; ++i)
	{
		int node=Q.front();
		Q.pop();
		inQ[node]=false;
		//bool stop = true;

		//for (node=0; node<n; ++node)
		for (int j=0; j<graph[node].size(); ++j)
		{
			if (capacity[node][graph[node][j].node] - flow[node][graph[node][j].node] > 0
				&& dist[node] + graph[node][j].cost < dist[graph[node][j].node])
			{
				dist[graph[node][j].node] = dist[node] + graph[node][j].cost;
				if(!inQ[graph[node][j].node])
				{
					if(count[graph[node][j].node]>n)
					{
						neg_cycle=true;
					}
					else
					{
						Q.push(graph[node][j].node);
						inQ[graph[node][j].node]=true;
						count[graph[node][j].node]++;
					}
				}
				//stop = false;
			}
		}
		
		//if (stop)
		//	break;
	}

	return neg_cycle;
}

int Dijkstra
(
	Graph& graph,
	int **capacity,
	int **flow,
	const int n,
	const uint16 src,
	const uint16 dest,
	int *dist,
	int &incDist,
	int &minFlow
)
{
	CHeap heap;
	short pred[n];
	
	for (int i=0; i<n; ++i)
	{
		for (int j=0; j<graph[i].size(); ++j)
		{
			if (dist[i] != INF && dist[graph[i][j].node] != INF)
				graph[i][j].cost = graph[i][j].cost + dist[i] - dist[graph[i][j].node];
		}
	}
	
	/*for (int i = 0; i < n; i++)
		cout << dist[i] << " ";
	cout << endl << endl;*/
	
	/*for (int i=0; i<n; ++i)
	{
		cout << i+1 << "-> ";
		for (int j=0; j<graph[i].size(); ++j)
		{
			cout << "(" << graph[i][j].node+1 << "," << graph[i][j].cost << ") ";
		}
		cout << "\n";
	}*/

	for(int i=0; i<n; ++i)
	{
		heap.insert(make_pair(INF,i));
		dist[i] = INF;
	}
	heap.modify(heap.getPos(1), make_pair(0,src));
	dist[src] = 0;
	
	//cout << "dist[dest] = " << dist[dest] << endl;
	
	//cout << "Initial heap\n";
	//heap.print();
	//cout << endl;
	
	while (!heap.empty())
	{
		const pair<int,uint16> node=heap.getElement(0);
		heap.remove(0);
		
		//cout << "Popped " << node.second+1 << endl;
		
		if (node.first==INF)
		{
			//cout << "Fail\n";
			break;
		}
		//dist[node.second] = node.first;

		for (vector<Edge>::iterator it=graph[node.second].begin(); it!=graph[node.second].end(); ++it)
		{
			const int alt = dist[node.second] + it->cost;
			
			if (capacity[node.second][it->node] - flow[node.second][it->node] > 0)
			{
				//cout << node.second+1 << "->" << it->node+1 << endl;
				assert(it->cost>=0);
			}
			
			if (alt<dist[it->node] &&
				capacity[node.second][it->node] - flow[node.second][it->node] > 0)
			{
				dist[it->node] = alt;
				//heap.print();
				//cout << "Modifying " << it->node+1 << " with " << dist[it->node] << endl;
				heap.modify(heap.getPos(it->node),make_pair(alt,it->node));
				//heap.print();
				pred[it->node] = node.second;
			}	
		}
	}
	
	//cout << "Ended\n";
	
	if (dist[dest] != INF)
	{
		minFlow = INF;
		
		for (int i=dest; i!=src; i=pred[i])
		{
			//cout << i+1 << "->";
			minFlow = minimum(minFlow, capacity[pred[i]][i] - flow[pred[i]][i]);
		}
		//cout << src+1 << endl;

		for (int i=dest; i!=src; i=pred[i]) 
		{
			flow[pred[i]][i] += minFlow;
			flow[i][pred[i]] -= minFlow;
		}

		/*cout << "dist[dest] = " << dist[dest] << endl;
		cout << "Current sum = " << incDist << endl;
		cout << "Current flow = " << minFlow << endl;
		cout << endl << endl;*/
		
		incDist += dist[dest];
		minFlow *= incDist;
		
		return true;
	}

	return false;
}

int EdmondsKarp
(
	Graph& graph,
	int **capacity,
	int **flow,
	const int n,
	const uint16 src,
	const uint16 dest,
	int *dist,
	int incDist
)
{
	int minFlow=0, curFlow;
	
	while (Dijkstra(graph, capacity, flow, n, src, dest, dist, incDist, curFlow))
	{
		minFlow += curFlow;
		//cout << "Current min flow = " << minFlow << endl;
	}
	
	return minFlow;
}

int main()
{
	int n,m;
	uint16 s,d;
	int **capacity, **flow, *dist;
	Graph graph;
	fstream fin("fmcm.in", fstream::in);
	fstream fout("fmcm.out", fstream::out);
	
	fin >> n >> m >> s >> d;
	//cout << n << " " << m << " " << s << " " << d << endl;
	
	// do allocations for memory
	graph.resize(n);
	capacity = new int*[n];
	flow = new int*[n];
	dist = new int[n+1];
	
	for (int i=0; i<n; ++i)
	{
		capacity[i] = new int[n];
		memset(capacity[i], 0, sizeof(int)*n);
		
		flow[i] = new int[n];
		memset(flow[i], 0, sizeof(int)*n);
	}
	
	// read our graph from the file
	for (int i=0; i<m; ++i)
	{
		int x, y, c, z;
		fin >> x >> y >> c >> z;
		
		graph[x-1].push_back(Edge(y-1, z));
		graph[y-1].push_back(Edge(x-1, -z));
		
		capacity[x-1][y-1] = c;
	}
	
	/*for (int i=0; i<n; ++i)
	{
		cout << i+1 << "-> ";
		for (int j=0; j<graph[i].size(); ++j)
		{
			cout << "(" << graph[i][j].node+1 << "," << graph[i][j].cost << ") ";
		}
		cout << "\n";
	}
	
	//Sum = -6
	cout << "\n";*/
	
	BellmanFord(graph, capacity, flow, n, s-1, dist);
	
	//out << dist[d-1] << "\n";
	
	const int incDist = dist[d-1];
	fout << EdmondsKarp(graph, capacity, flow, n, s-1, d-1, dist, incDist) << endl;
	
	fin.close();
	fout.close();
	return 0;
}