Cod sursa(job #633432)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 13 noiembrie 2011 19:33:01
Problema Cuplaj maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.9 kb
#include <fstream>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <bitset>

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

#define MAXN 700
#define INF 0x3f3f3f3f

using namespace std;

typedef unsigned short uint16;
typedef unsigned int uint32;

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

typedef vector<vector<Edge> > Graph;

inline void AddSource(Graph& graph, const uint16 n, int** capacity)
{
	for (int i=1; i<=n; ++i)
	{
		graph[i].push_back(Edge(0,0));
		graph[0].push_back(Edge(i,0));
		
		capacity[0][i] = 1;
	}
}

inline void AddSink(Graph& graph, const uint16 n, const uint16 m, int** capacity)
{
	const uint16 dest = n+m+1;
	for (int i=1; i<=m; ++i)
	{
		graph[n+i].push_back(Edge(dest,0));
		graph[dest].push_back(Edge(n+i,0));
		
		capacity[n+i][dest] = 1;
	}
}

bool BellmanFord(const Graph &graph,
				 int **capacity,
				 int **flow,
				 const uint32 n,
				 const uint16 s,
				 int dist[],
				 int& minFlow
				)
{
	queue<uint16> Q;
	uint16 count[MAXN]={0};
	int parent[MAXN]={-1};
	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)
	{
		const uint16 node=Q.front();
		Q.pop();
		inQ[node]=false;

		for (uint32 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;
				parent[graph[node][j].node] = node;
				
				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]++;
					}
				}
			}
		}
	}
	
	minFlow = INF;
	if (dist[n-1] < INF)
	{	
		for (int i=n-1; i>0; i = parent[i])
		{
			//cout << i << " ";
			minFlow = minimum(minFlow, capacity[parent[i]][i] - flow[parent[i]][i]);
		}
		//cout << endl;
		
		for (int i=n-1; i>0; i = parent[i])
		{
			flow[parent[i]][i] += minFlow;
			flow[i][parent[i]] -= minFlow;
		}
		
		//cout << "dist[n-1] = " << dist[n-1] << endl;
		//cout << "minFlow = " << minFlow << endl;
		
		minFlow *= dist[n-1];
		
		
		//cout << "Current flow is = " << minFlow << endl << endl;
	}

	return neg_cycle;
}

int MinimumCostMaximumMatching
(
	const Graph& graph,
	uint32 uGraphSize,
	int **capacity,
	int **flow,
	int dist[]
)
{
	int minFlow = 0;
	int totalMinFlow = 0;

	while (minFlow != INF)
	{
		totalMinFlow += minFlow;
		BellmanFord(graph, capacity, flow, uGraphSize, 0, dist, minFlow);
	}
	
	return totalMinFlow;
}

int ConstructSolution
(
	const uint16 n,
	const uint16 m,
	int** capacity,
	int** flow,
	int** edgeIndices,
	/*[out]*/vector<uint16>& vEdges
)
{
	int numEdges = 0;

	for (uint16 i=1; i<=n; ++i)
	{
		for (uint16 j=n+1; j<=n+m+1; ++j)
		{
			if (capacity[i][j] && flow[i][j])
			{
				numEdges++;
				vEdges.push_back(edgeIndices[i][j]);
				break;
			}
		}
	}
	
	return numEdges;
} 

int main()
{
	uint16 n,m;
	uint32 E;
	int **capacity, **flow, **edgeIndices, *dist;
	fstream fin("cmcm.in", fstream::in);
	fstream fout("cmcm.out", fstream::out);
	Graph graph;
	vector<uint16> vEdges;
	
	fin >> n >> m >> E;
	//cout << n << " " << m << " " << E << endl;
	
	const uint16 uGraphSize = n+m+2;
	
	graph.resize(uGraphSize);
	dist = new int[uGraphSize];

	capacity = new int*[uGraphSize];
	flow = new int*[uGraphSize];
	edgeIndices = new int*[uGraphSize];
	for (int i=0; i<uGraphSize; ++i)
	{
		capacity[i] = new int[uGraphSize];
		memset(capacity[i], 0, sizeof(int)*uGraphSize);
		
		flow[i] = new int[uGraphSize];
		memset(flow[i], 0, sizeof(int)*uGraphSize);
		
		edgeIndices[i] = new int[uGraphSize];
		memset(edgeIndices[i], 0, sizeof(int)*uGraphSize);
	}
	
	// read and build graph
	for (uint32 i=0; i<E; ++i)
	{
		uint16 x, y;
		short c;
		fin >> x >> y >> c;
		
		//cout << x << " " << y << " " << c << endl;
		
		graph[x].push_back(Edge(n+y,c));
		graph[n+y].push_back(Edge(x,-c));
		
		capacity[x][n+y] = 1;
		edgeIndices[x][n+y] = i;
	}
	
	AddSource(graph, n, capacity);
	AddSink(graph, n, m, capacity);
	
	// perform minim cost matching
	int totalMinFlow = MinimumCostMaximumMatching(graph, uGraphSize, capacity, flow, dist);
	//cout << totalMinFlow << endl;
	
	int numEdges = ConstructSolution(n, m, capacity, flow, edgeIndices, vEdges);
	
	fout << numEdges << " " << totalMinFlow << "\n";
	for (uint16 i=0; i<numEdges; ++i)
		fout << vEdges[i]+1 << " ";
	fout << "\n";
	
	fin.close();
	fout.close();
	return 0;
}