Cod sursa(job #1966040)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 14 aprilie 2017 20:40:00
Problema Flux Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.86 kb
#include <fstream>
#include <iomanip>
#include <algorithm>

using namespace std;

const int NMAX = 100 + 5;
const double EPS = 1E-8;

int N;
double mat[NMAX][NMAX];

void _swap(int lin1, int lin2, int start) {
    for (int i = start; i <= N + 1; ++ i)
        swap(mat[lin1][i], mat[lin2][i]);
}
void mult(int lin, double val, int start) {
    for (int i = start; i <= N + 1; ++ i)
        mat[lin][i] *= val;
}
void subtr(int lin1, double alpha, int lin2, int start) {
    for (int i = start; i <= N + 1; ++ i)
        mat[lin1][i] -= alpha * mat[lin2][i];
}

double potentials[NMAX];
void Gauss() {
    for (int col = 1; col <= N; ++ col) {
        int who = 0;
        for (int i = col; i <= N; ++ i)
            if (fabs(mat[i][col]) >= EPS) {
                who = i;
                break;
            }

        _swap(col, who, col);
        mult(col, 1 / mat[col][col], col);

        for (int i = col + 1; i <= N; ++ i)
            if (fabs(mat[i][col]) >= EPS)
                subtr(i, mat[i][col], col, col);
    }

    for (int i = N; i; -- i) {
        potentials[i] = mat[i][N + 1];
        for (int j = i + 1; j <= N; ++ j)
            potentials[i] -= potentials[j] * mat[i][j];
    }
}

const int MMAX = 5000 + 5;
struct Edge {
    int a, b, c;
} edges[MMAX];

vector <int> graph[NMAX];

int label[NMAX];
int labels;
void dfs(int node) {
    label[node] = ++ labels;
    for (auto it: graph[node])
        if (!label[it])
            dfs(it);
}

vector <int> newGraph[NMAX];

int main()
{
    ifstream cin("flux.in");
    ofstream cout("flux.out");

    int M = 0;
    cin >> N >> M;

    for (int i = 1; i <= M; ++ i) {
        cin >> edges[i].a >> edges[i].b >> edges[i].c;
        graph[edges[i].a].push_back(edges[i].b);
        graph[edges[i].b].push_back(edges[i].a);
    }

    //Relabel
    dfs(1);
    int T = label[N];
    for (int i = 1; i <= M; ++ i) {
        edges[i].a = label[edges[i].a];
        edges[i].b = label[edges[i].b];
        newGraph[edges[i].a].push_back(edges[i].b);
        newGraph[edges[i].b].push_back(edges[i].a);
    }
    N = labels;

    //Find potentials
    potentials[1] = 0;
    mat[1][1] = 1;
    mat[1][N + 1] = 0;

    potentials[T] = 1;
    mat[T][T] = 1;
    mat[T][N + 1] = 1;

    for (int i = 2; i <= N; ++ i)
        if (i != T) {
            mat[i][i] = newGraph[i].size();
            for (auto it: newGraph[i])
                -- mat[i][it];
        }
    Gauss();

    //Compute MaxFlow
    double atMost = 1E9;
    for (int i = 1; i <= M; ++ i)
        if (edges[i].a)
            atMost = min(atMost, edges[i].c / fabs(potentials[edges[i].a] - potentials[edges[i].b]));

    double flow = 0;
    for (auto it: newGraph[1])
        flow += atMost * potentials[it];
    cout << fixed << setprecision(6) << flow << '\n';
    return 0;
}