Cod sursa(job #2269407)

Utilizator b10nd3Oana Mancu b10nd3 Data 25 octombrie 2018 22:31:32
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.83 kb
#include<iostream>
#include<fstream>
#include<vector>
#include<queue>

using namespace std;

#define NMAX 610
#define INF 0x3f3f3f3f

int n, m, e, dest;
int edge[NMAX][NMAX], C[NMAX][NMAX], F[NMAX][NMAX];
vector<int> adj[NMAX], cost[NMAX];

void read(){
	FILE *in = fopen("cmcm.in","r");
	int x, y, c;
	
	fscanf(in,"%i %i %i", &n, &m, &e);
	for(int i=1; i<=e; i++){
	     
		 fscanf(in, "%i %i %i", &x, &y, &c);
		 x++; y += n+1; // 1- nod start; [2,n+1] - noduri multime Left; [n+2, n+2+m-1] - noduri multime Right; n+2+m - nod destinatie
		 adj[x].push_back(y); adj[y].push_back(x);
		 cost[x].push_back(c); cost[y].push_back(-c);
		 edge[x][y] = i;
		 C[x][y] = 1;	
	}
	dest = n+m+2;
	fclose(in);
}


void fillGraph(int x, int y){
	
	adj[x].push_back(y); adj[y].push_back(x);
	cost[x].push_back(0); cost[y].push_back(0);
	C[x][y] = 1;
}


void completeGraph(){  
	
	int i;
	
	//unesc nodul start cu toate nodurile din Left
	for(i=2;i<=n+1;i++)
		fillGraph(1,i);
	
	//unesc nodul destinatie cu toate nodurile din Right
	for(i=n+2; i<=dest; i++)
		fillGraph(i,dest);
}


int BellmanFord(){
	
	// declar. vars
	int fMin = INF, x, y, nod;
	int costMin[n+m+7], T[n+m+7];
	bool inQueue[n+m+7];
	queue<int> q;
	
	//initializare Bellman-Ford
	for(int i = 1; i <= dest; i++){
		costMin[i] = INF;
		T[i] = -1;
		inQueue[i] = false;
	}
	
	inQueue[1] = true; q.push(1); costMin[1] = 0;  
	
	//Bellman-Ford - main thing
	while(!q.empty()){
			x = q.front(); q.pop(); inQueue[x] = false;
			for( size_t i=0; i<adj[x].size(); i++ ){
				y = adj[x][i]; 
				if( F[x][y] < C[x][y] && costMin[y] > costMin[x] + cost[x][i] ){
					costMin[y] = costMin[x] + cost[x][i];
					T[y] = x;
					if(!inQueue[y]){
						inQueue[y] = true;
						q.push(y);
					} 
				} 
			}
	}
	
	
	//nu am mai gasit drum nesaturat de la sursa la destinatie
	if(costMin[dest] == INF) return 0;
	

	for(nod = dest; nod != 1; nod = T[nod])
	   fMin = min( fMin, C[ T[nod] ][nod] - F[ T[nod] ][nod] );  // fMin - fluxul pe care il pot transporta pe acest drum;
    for(nod = dest; nod != 1; nod = T[nod]){ //reactualizez F cu fMin;
    	F[ T[nod] ][nod] += fMin;
    	F[nod][ T[nod] ] -= fMin;
	}	   	
	return costMin[dest] * fMin; // costul lui fMin
}


void write(int sol){
    
	FILE *out = fopen("cmcm.out","w");
	int nr=0;
	queue<int> q;
	
	for(int i=2; i<=n+1; i++)
	   for(int j=n+2; j<dest; j++)
	      if( C[i][j] && F[i][j]){
	      	nr++;
	      	q.push( edge[i][j] );
	      	break;
		  }
	
	fprintf(out,"%d %d\n", nr, sol);
	
	while(!q.empty()){
		fprintf(out,"%i ",q.front());
		q.pop();
	}
	
	fclose(out);	
}

int main(){
	
	read();
	
	completeGraph();
	
	int improve = 1, sol = 0;
	while (improve){
		improve = BellmanFord();
		sol += improve;
	}
	
	write(sol);
	
	return 0;
}