Cod sursa(job #989566)

Utilizator Cosmin1490Balan Radu Cosmin Cosmin1490 Data 25 august 2013 21:56:46
Problema Cuplaj maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 5.84 kb
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <fstream>
using namespace std;
  
const string file = "cmcm";
  
const string infile = file + ".in";
const string outfile = file + ".out";

int N, M, E;
int S, D;
int MinCost;

struct Arc
{
	int dst;
	int cap;
	int flux;
	int cost;
	int p;

	Arc(int dst, int cap, int cost, int p)
	{
		this->flux = 0;
		this->dst = dst;
		this->cap = cap;
		this->cost = cost;
		this->p = p;
	}

};

const int INF = 0x3f3f3f3f;

vector<Arc> arcs;
vector<vector<int> > G;

vector<int> potential;
vector<int> realD;
vector<int> potD;

vector<int> dijArc;
vector<int> dijParent;


vector<int> heap;
vector<int> poz;

void initHeap()
{
	heap.reserve(N + M + 3);
	heap.push_back(0);
	poz.resize(N + M + 3);
}

inline int father(int i)
{
	return i / 2;
}

inline int lSon(int i)
{
	return i * 2;
}

inline int rSon(int i)
{
	return i * 2;
}

void swapHeap(int a, int b)
{
	int aux = heap[a];
	heap[a] = heap[b];
	heap[b] = aux;
	poz[heap[a]] = a;
	poz[heap[b]] = b;
}


void upHeap(int i)
{
	while( i > 1 && potD[heap[i]] < potD[heap[father(i)]])
	{
		swapHeap(i, father(i));
		i = father(i);
	}
}

void downHeap(int i)
{
	while(true)
	{
		int size = heap.size();
		int min = i;

		if(lSon(i) < size && potD[heap[lSon(i)]] < potD[heap[min]])
			min = lSon(i);

		if(rSon(i) < size && potD[heap[rSon(i)]] < potD[heap[min]])
			min = rSon(i);
		if(min == i) 
			break;
		swapHeap(i, min);
		i = min;

	}
}

int topHeap()
{
	return heap[1];
}

void insertHeap(int i)
{
	poz[i] = heap.size();
	heap.push_back(i);
	upHeap(heap.size() - 1);
}

void popHeap()
{
	swapHeap(1, heap.size() - 1);
	poz[heap[heap.size() - 1]] = 0;
	heap.pop_back();
	downHeap(1);
}

bool emptyHeap()
{
	return heap.size() <= 1;
}

void Bellman()
{
	potential.resize(N + M + 3, INF);
	queue<int> q;
	vector<bool> inQ(N + M + 3);
	q.push(S);
	potential[S] = 0;

	while(q.empty() == false)
	{
		int current = q.front();
		q.pop();
		inQ[current] = false;
		for(vector<int>::iterator itr = G[current].begin();
			itr != G[current].end();
			itr++)
		{
			if(arcs[*itr].cap - arcs[*itr].flux > 0)
			{
				if(potential[arcs[*itr].dst] > potential[current] + arcs[*itr].cost)
				{
					potential[arcs[*itr].dst] = potential[current] + arcs[*itr].cost;

					if(inQ[arcs[*itr].dst] == false)
					{
						q.push(arcs[*itr].dst);
						inQ[arcs[*itr].dst] = true;
					}
				}
			}
		}
	}
}

bool Dijkstra()
{
	potD.clear();
	potD.resize(N + M + 3, INF);
	potD[S] = 0;
	realD[S] = 0;

	insertHeap(S);

	while(emptyHeap() == false)
	{
		int current = topHeap();
		popHeap();

		for(vector<int>::iterator itr = G[current].begin();
			itr != G[current].end();
			itr++)
		{
			if(arcs[*itr].cap - arcs[*itr].flux > 0)
			{
				int newCost = arcs[*itr].cost + potential[current] - potential[arcs[*itr].dst];

				if(potD[arcs[*itr].dst] > potD[current] + newCost)
				{
					potD[arcs[*itr].dst] = potD[current] + newCost;
					realD[arcs[*itr].dst] = realD[current] + arcs[*itr].cost;

					dijParent[arcs[*itr].dst] = current;
					dijArc[arcs[*itr].dst] = *itr;

					if(poz[arcs[*itr].dst] == 0)
					{
						insertHeap(arcs[*itr].dst);
					}
					else
					{
						upHeap(poz[arcs[*itr].dst]);
					}

				}
			}
		}
	}

	potential = realD;

	if(potD[D] == INF) return false;
	return true;
}


int main()
{
	fstream fin(infile.c_str(), ios::in);

	fin >> N >> M >> E;

	G.resize(N + M + 1 + 2);
	arcs.reserve(2 * E + 2 * N + 2 * M);
	S = N + M + 1;
	D = N + M + 2;

	for(int i = 0; i < E; i++)
	{
		int x, y, c;
		fin >> x >> y >> c;

		y += N;

		G[x].push_back(arcs.size());
		G[y].push_back(arcs.size() + 1);

		Arc to(y, 1, c, arcs.size() + 1);
		Arc from(x, 0, -c, arcs.size());

		arcs.push_back(to);
		arcs.push_back(from);

	}


	for(int i = 1; i <= N; i++)
	{
		int x, y, c;
		x = S;
		y = i;
		c = 0;

		G[x].push_back(arcs.size());
		G[y].push_back(arcs.size() + 1);

		Arc to(y, 1, c, arcs.size() + 1);
		Arc from(x, 0, -c, arcs.size());

		arcs.push_back(to);
		arcs.push_back(from);
	}


	for(int i = N + 1; i <= N + M; i++)
	{
		int x, y, c;
		x = i;
		y = D;
		c = 0;

		G[x].push_back(arcs.size());
		G[y].push_back(arcs.size() + 1);

		Arc to(y, 1, c, arcs.size() + 1);
		Arc from(x, 0, -c, arcs.size());

		arcs.push_back(to);
		arcs.push_back(from);
	}
	fin.close();

	Bellman();

	realD.resize(N + M + 3);
	dijArc.resize(N + M + 3);
	dijParent.resize(N + M + 3);

	initHeap();

	while(Dijkstra())
	{
		int maxFlow = INF;

		for(int current = D; current != S; current = dijParent[current])
		{
			maxFlow = min(maxFlow, arcs[dijArc[current]].cap - arcs[dijArc[current]].flux);
		}

		for(int current = D; current != S; current = dijParent[current])
		{
			arcs[dijArc[current]].flux += maxFlow;
			arcs[arcs[dijArc[current]].p].flux -= maxFlow;
		}

		MinCost += maxFlow * realD[D];

	}
	
	int count = 0;
	/*
	for(int i = 0; i < 2 * E; i+=2)
	{
		if(arcs[i].flux != 0) 
			count++;
	}
	*/
	fstream fout(outfile.c_str(), ios::out);
	//cout << count << " " << MinCost << "\n";
	fout << count << " " << MinCost << "\n";
	
	/*
	for(int i = 0; i < 2 * E; i+=2)
	{
		if(arcs[i].flux != 0)
		{
			//cout << (i / 2) + 1 << " ";
			fout << (i / 2) + 1 << " ";
		}
	}
	fout << "\n";
	*/
	fout.close();
}