Cod sursa(job #989589)

Utilizator Cosmin1490Balan Radu Cosmin Cosmin1490 Data 25 august 2013 22:54:03
Problema Cuplaj maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 5.73 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;

#define MAXN 605

int Cost[MAXN][MAXN];
int Cap[MAXN][MAXN];
int Flux[MAXN][MAXN];
int Idx[MAXN][MAXN];
/*

vector<vector<int> > Cost;
vector<vector<int> > Cap;
vector<vector<int> > Flux;
vector<vector<int> > Idx;

*/

const int INF = 0x3f3f3f3f;

vector<vector<int> > G;

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

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;
}

inline 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(Cap[current][*itr] - Flux[current][*itr] > 0)
			{
				if(potential[*itr] > potential[current] + Cost[current][*itr])
				{
					potential[*itr] = potential[current] + Cost[current][*itr];

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


//priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > heapQ;

bool Dijkstra()
{
	fill(potD.begin(), potD.end(), INF);
	
	/*
	potD.clear();
	potD.resize(N + M + 3, INF);
	*/

	potD[S] = 0;
	realD[S] = 0;

	//heapQ.push(make_pair(0, S));

	insertHeap(S);
	
	while(emptyHeap() == false)
	//while(heapQ.empty() == false)
	{
		/*
		int cost = heapQ.top().first;
		int current = heapQ.top().second;
		heapQ.pop();
		if(potD[current] != cost) continue;
		*/
		
		int current = topHeap();
		popHeap();
		

		for(vector<int>::iterator itr = G[current].begin();
			itr != G[current].end();
			itr++)
		{
			if(Cap[current][*itr] - Flux[current][*itr] > 0)
			{
				int newCost = Cost[current][*itr] + potential[current] - potential[*itr];

				if(potD[*itr] > potD[current] + newCost)
				{
					potD[*itr] = potD[current] + newCost;
					realD[*itr] = realD[current] + Cost[current][*itr];

					dijParent[*itr] = current;

					//heapQ.push(make_pair(potD[*itr], *itr));
					
					if(poz[*itr] == 0)
					{
						insertHeap(*itr);
					}
					else
					{
						upHeap(poz[*itr]);
					}
					
				}
			}
		}
	}

	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);

	/*
	Flux.resize(N + M + 3, vector<int>(N + M + 3));
	Cap.resize(N + M + 3, vector<int>(N + M + 3));
	Cost.resize(N + M + 3, vector<int>(N + M + 3));
	Idx.resize(N + M + 3, vector<int>(N + M + 3));
	*/
	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(y);
		G[y].push_back(x);

		Cost[x][y] = c;
		Cost[y][x] = -c;
		Cap[x][y] = 1;

		Idx[x][y] = i + 1;
	}


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

		G[x].push_back(y);
		G[y].push_back(x);
		Cap[x][y] = 1;
	}


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


		G[x].push_back(y);
		G[y].push_back(x);

		Cap[x][y] = 1;
	}
	fin.close();

	Bellman();

	realD.resize(N + M + 3);
	dijParent.resize(N + M + 3);
	potD.resize(N + M + 3);
	initHeap();

	while(Dijkstra())
	{
		for(int current = D; current != S; current = dijParent[current])
		{
			Flux[dijParent[current]][current] += 1;
			Flux[current][dijParent[current]] -= 1;

		}
		MinCost += realD[D];
		//cout << MinCost << "\n";
	}
	
	int count = 0;

	for(int i = 1; i <= N; i++)
	{
		for(int j = N + 1; j <= N + M; j++)
		{
			if(Flux[i][j]) 
				count++;
		}
	}

	fstream fout(outfile.c_str(), ios::out);
	fout << count << " " << MinCost << "\n";
	for(int i = 1; i <= N; i++)
	{
		for(int j = N + 1; j <= N + M; j++)
		{
			if(Flux[i][j])
			{
				fout << Idx[i][j] << " ";
			}
		}
	}
	fout << "\n";
	fout.close();
}