Cod sursa(job #1160997)

Utilizator SRaduRadu Szasz SRadu Data 30 martie 2014 22:33:58
Problema Flux Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.27 kb
#include <iostream>
#include <cstdio>
#include <iomanip>

using namespace std;

const int MAX = 111;
const double EPS = 1e-9;
const double INF = (10000.0 * 10000.0 * 100.0);

int N, M;
int Capacity[MAX][MAX], isEdge[MAX][MAX];

double Ans, D[MAX];
double G[MAX][MAX];

bool noSolution;
bool Visited[MAX];

void OpenFiles() {
    freopen("flux.in", "r", stdin);
    freopen("flux.out", "w", stdout);
    freopen("debug.out", "w", stderr);
}

void CloseFiles() {
    fclose(stdin);
    fclose(stdout);
    fclose(stderr);
}

double fabs(double A) {
    if(A < 0)
        return -A;
    return A;
}

bool EQUAL(double A, double B) {
    if(fabs(A - B) < EPS) 
        return true;
    return false;
}

void Citire() {
    cin >> N >> M;
    for(int i = 1, A, B, C; i <= M; i++) {
        cin >> A >> B >> C;
        if(!isEdge[A][B]) {
            Capacity[A][B] = Capacity[B][A] = C;
        } else {
            Capacity[A][B] = Capacity[B][A] = min(Capacity[A][B], C);
        }
        isEdge[A][B]++;
        isEdge[B][A]++;
    }
}

void Dfs(int nod) {
    Visited[nod] = true;
    for(int i = 1; i <= N; i++) {
        if(Visited[i] || !isEdge[nod][i])
            continue;
        Dfs(i);
    }
}

void BuildGauss() {
    for(int i = 2; i <= N; i++) {
        for(int j = 1; j <= N; j++) {
            if(i == j)
                continue;
            G[i][i] += isEdge[i][j];
            if(j != 1)
                G[i][j] -= isEdge[i][j];
        }
    }
    G[N][N + 1] = 1.0;
}

void afisareGauss() {
    for(int i = 2; i <= N; i++) {
        for(int j = 1; j <= N + 1; j++)
            cerr << G[i][j] << " ";
        cerr << "\n";
    } cerr << "\n";
}

void SolveGauss() {
    int i = 2, j = 2, k;
    while(i <= N && j <= N) {
        int eq = 0;
        for(k = i; k <= N; k++)
            if(!EQUAL(G[k][j], 0.0)) {
                eq = k;
                break;
            }
        if(!eq) {
            j++;
            continue;
        }
        
        for(k = 1; k <= N + 1; k++)
            swap(G[i][k], G[eq][k]);
        
        for(k = j + 1; k <= N + 1; k++)
            G[i][k] /= G[i][j];
        G[i][j] = 1.0;

        for(eq = i + 1; eq <= N; eq++) {
            if(!EQUAL(G[eq][j], 0.0)) {
                for(k = j + 1; k <= N + 1; k++)
                    G[eq][k] -= G[i][k] * G[eq][j];
                G[eq][j] = 0.0;
            }
        }
        i++, j++;
    }
    for(i = N; i > 1; i--) {
        for(j = 1; j <= N + 1; j++) {
            if(!EQUAL(G[i][j], 0.0)) {
                if(j == N + 1) 
                    noSolution = true;
                D[j] = G[i][N + 1];
                
                for(k = i - 1; k > 1; k--) {
                    G[k][N + 1] -= G[k][j] * D[j];
                    G[k][j] = 0.0;
                }
                break;
            }
        }
    }
}

void AdjustGauss() {
    Ans = INF;
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= N; j++) {
            if(i == j || !isEdge[i][j]) continue;
            Ans = min(Ans, (1.0 * Capacity[i][j]) / fabs(D[j] - D[i]));
        }
}

int main() {
    OpenFiles();
    Citire();
    Dfs(1);
    if(Visited[N]) {
        BuildGauss();
        SolveGauss();
        if(!noSolution)
            AdjustGauss();
    }
    cout << fixed << setprecision(6) << Ans << "\n";
    CloseFiles();
    return 0;
}