Cod sursa(job #587204)

Utilizator perticas_catalinperticas catalin perticas_catalin Data 4 mai 2011 03:19:16
Problema Flux Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.16 kb
#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>

using namespace std;

#define NM 105
#define MM 10005
#define EPS 0.0000000001
#define PB push_back
#define MKP make_pair

vector <pair <int, int> > G[NM], NG[NM];
int fN, fM;
bool viz[NM];

double ab (double val)
{
    if (val < 0) return -val;
    return val;
}

int iszero (double val)
{
    if (ab(val) < EPS) return 1;
    return 0;
}

class gaussian_elimination
{
    int N;
    double matrix[NM][NM];

    void swap_rows (int r1, int r2)
    {
        for (int i = 1; i <= N + 1; ++i)
        {
            double aux = matrix[r1][i];
            matrix[r1][i] = matrix[r2][i];
            matrix[r2][i] = aux;
        }
    }

    void substract_rows (int r1, int r2, double val)
    {
        for (int i = 1; i <= N + 1; ++i) matrix[r1][i] -= matrix[r2][i] * val;
    }

    public:

    void set_system (int cN, double cmatrix[NM][NM])
    {
        N = cN;
        for (int i = 1; i <= N; ++i)
            for (int j = 1; j <= N + 1; ++j) matrix[i][j] = cmatrix[i][j];
    }

    vector <double> solve_system ()
    {
        for (int i = 1; i < N; ++i)
        {
            if (iszero(matrix[i][i]))
                for (int j = i + 1; j <= N; ++j)
                    if (!iszero(matrix[j][i]))
                    {
                        swap_rows(i, j);
                        break;
                    };


            for (int j = i + 1; j <= N; ++j) substract_rows(j, i, matrix[j][i]/matrix[i][i]);
        }

        vector <double> ans;

        for (int i = N; i >= 1; --i)
            for (int j = 1; j < i; ++j) substract_rows(j, i, matrix[j][i]/matrix[i][i]);

        for (int i = 1; i <= N; ++i) ans.push_back(matrix[i][N+1]/matrix[i][i]);

        return ans;

    }
};

void df (int nod)
{
    viz[nod] = 1;
    for (int i = 0; i < G[nod].size(); ++i)
    {
        int nnod = G[nod][i].first;
        if (viz[nnod]) continue;
        df (nnod);
    }
}

int check_connectivity_and_create_graph()
{
    df(1);
    if (!viz[fN]) return 0;

    int ce_nod[NM], noduri = 0;
    memset (ce_nod, 0, sizeof(ce_nod));

    for (int i = 2; i <= fN; ++i)
        if (viz[i])
        {
            ++noduri;
            ce_nod[i] = noduri;
        }

    for (int i = 2; i <= fN; ++i)
    {
        if (!viz[i]) continue;
        int rnod = ce_nod[i];

        for (int j = 0; j < G[i].size(); ++j)
        {
            int rnnod = ce_nod[G[i][j].first];
            int c = G[i][j].second;
            NG[rnod].PB(MKP(rnnod, c));
        }
    }

    return noduri;
}

int main()
{
    freopen ("flux.in", "r", stdin);
    freopen ("flux.out", "w", stdout);

    int cN;
    double cmatrix[NM][NM];

    memset (cmatrix, 0, sizeof(cmatrix));

    scanf ("%d %d", &fN, &fM);

    for (int i = 1; i <= fM; ++i)
    {
        int a, b, c;

        scanf ("%d %d %d", &a, &b, &c);
        G[a].PB(MKP(b, c));
        G[b].PB(MKP(a, c));
    }

    cN = check_connectivity_and_create_graph();
    if (!cN)
    {
        printf ("0.0000000");
        return 0;
    }

    for (int i = 1; i <= cN; ++i)
        for (int j = 0; j < NG[i].size(); ++j)
        {
            int nod = NG[i][j].first;
            if (nod) cmatrix[i][nod] += 1;
            cmatrix[i][i] -= 1;
        }

    cmatrix[cN][cN + 1] = -1;

    gaussian_elimination syst;
    syst.set_system(cN, cmatrix);
    vector <double> ans = syst.solve_system();

    //printf ("%lf\n", ans[ans.size() - 1]);

    double smax = 2000000000.0;

    for (int i = 1; i <= cN; ++i)
        for (int j = 0; j < NG[i].size(); ++j)
        {
            int nod = NG[i][j].first;
            int c = NG[i][j].second;
            double a, b;
            if (!nod) a = 0.0;
            else a = ans[nod-1];
            b = ans[i-1];
            double cc = ab(b-a);
            if (!iszero(cc)) smax = min(smax, (double)c/cc);
        }

    /*
    printf ("%d\n", cN);

    for (int i = 1; i <= cN; ++i)
    {
        for (int j = 0; j < NG[i].size(); ++j)
            printf ("(%d,%d) ", NG[i][j].first, NG[i][j].second);

        printf ("\n");
    }

    for (int i = 0; i < ans.size(); ++i) printf ("%lf ", ans[i]);

    printf ("\n");
    */

    printf ("%lf", smax);

    return 0;
}