Cod sursa(job #74393)

Utilizator DITzoneCAdrian Diaconu DITzoneC Data 25 iulie 2007 14:02:14
Problema Flux Scor Ascuns
Compilator cpp Status done
Runda Marime 3.56 kb
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>

using namespace std;

#define MAX_N 100

//useful floating-point macros
#define EPS 	0.000000000001
#define ISZERO(x)  (fabs(x) <= EPS)

void swap_rows(long double (*equations) [MAX_N+1], int n, int a, int b)
{
    for(int i=0; i<n+1; i++)
	swap(equations[a][i], equations[b][i]);
}


void multiply_row(long double (*equations) [MAX_N+1], int n, int a, long double x)
{
    for(int i=0; i<n+1; i++)
	equations[a][i] *= x;
}

void subtract_row(long double (*equations) [MAX_N+1], int n, int a, int b, long double x)
{
    for(int i=0; i<n+1; i++)
	equations[a][i] -= equations[b][i]*x;
}


//Gaussian elimination - hope it's accurate enough

void solve_system(long double (*equations) [MAX_N+1], int n)
{
    int row, column;
    row = 0;
    column = 0;
    while(row < n && column < n)
    {
	if(ISZERO(equations[row][column]))
	{
	    for(int j=row+1; j<n; j++)
	    {
		if(!ISZERO(equations[j][column]))
		{
		    swap_rows(equations, n, row, j);
		    break;
		}
	    }
	}
	if(ISZERO(equations[row][column]))
	{
	    column ++;
	    continue;
	}
	multiply_row(equations, n, row, 1.0/equations[row][column]);
	for(int j=0; j<n; j++)
	{
	    if(row == j) continue;
	    if(!ISZERO(equations[j][column]))
	    {
		subtract_row(equations, n, j, row, equations[j][column]);
	    }
	}
	row++;
	column++;
    }
    for(int i=0; i<n; i++)
    {
	if(ISZERO(equations[i][i]))
	{
	    equations[n-1][i] = 1;
	    equations[n-1][n] = 1;
	    solve_system(equations, n);
	    break;
	}
    }
}

void compute_flow(int (*max_flow)[MAX_N], int (*pipes)[MAX_N], int n)
{
    long double equations[MAX_N+1][MAX_N+1];
    long double copy[MAX_N+1][MAX_N+1];
    for(int i=1; i<n; i++) //conservation law for vertex i+1
    {
	for(int j=0; j<=n; j++) //the last column is reserved for result
	    equations[i-1][j] = 0;
	if(i == n-1)
	    equations[i-1][i] = 1;
	else
	for(int j=0; j<n; j++)
	{
	    if(i == j)
		continue;
	    //there exists a pipe between j and i
	    if(pipes[j][i])
	    {
		equations[i-1][i] += pipes[j][i];
		equations[i-1][j] -= pipes[j][i];
	    }
	}
    }
    for(int i=0; i<=n; i++)
	equations[n-1][i] = 0;
    long double max_scale=-100;
    for(int i=0; i<=n; i++)
    for(int j=0; j<=n; j++)
	copy[i][j] = equations[i][j];
    solve_system(equations, n);
    for(int i=0; i<n; i++)
    for(int j=0; j<n; j++)
    {
	if(pipes[i][j] == 0) continue;
	if(!ISZERO(equations[i][n]-equations[j][n]) && (max_scale < 0 || 
	     ((long double)(max_flow[i][j]))/fabs(equations[i][n]-equations[j][n]) < max_scale))
	{
	    
	    max_scale = ((long double)(max_flow[i][j]))/fabs(equations[i][n]-equations[j][n]);
	}
    }
    long double res;
    res = 0;
    for(int i=1; i<n; i++)
    {
	if(pipes[0][i])
	    res += (equations[0][n] - equations[i][n])*pipes[0][i];
    }
    printf("%.6Lf\n", res*max_scale);
}

void read_input(int (*max_flow)[MAX_N], int (*pipes)[MAX_N], int n, int m)
{
    int a, b, c;
    for(int i=0; i<n; i++)
    for(int j=0; j<n; j++)
    {
	max_flow[i][j] = 0;
	pipes[i][j] = 0;
    }
    for(int i=0; i<m; i++)
    {
	scanf("%d%d%d", &a, &b, &c); 
	a --; b --;
	
	if(pipes[a][b] == 0)
	    max_flow[a][b] = max_flow[b][a] = c;
	else
	{
	    max_flow[a][b] = min(max_flow[a][b], c);
	    max_flow[b][a] = min(max_flow[b][a], c);
	}
	pipes[a][b] ++;
	pipes[b][a] ++;
    }
}

int main()
{
	freopen("flux.in","r",stdin);
	freopen("flux.out","w",stdout);
    int n, m;
    scanf("%d%d", &n, &m);
    int max_flow[MAX_N][MAX_N], pipes[MAX_N][MAX_N];
    
    read_input(max_flow, pipes, n, m);
    compute_flow(max_flow, pipes, n);
    return 0;
}