Cod sursa(job #1821261)

Utilizator oldatlantianSerban Cercelescu oldatlantian Data 2 decembrie 2016 20:44:55
Problema Tunelul groazei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.1 kb
#include <bits/stdc++.h>
using namespace std;
typedef double f64; // long double is still the best

const int SPQR = 256, // Ave Imperator, morituri te salutant!
          BMAX = 1 << 17;
const f64 EPS = 1e-7;

struct EDGE {
    int v, w;

    inline EDGE() { }
    inline EDGE(int _v, int _w) {
        v = _v;
        w = _w; } };

vector<f64> vals;

char buck[BMAX];
vector<EDGE> g[SPQR];
valarray<f64> gs[SPQR];

inline bool eq(const f64 &a, const f64 &b) {
    return abs(a - b) < EPS; }

inline char nextch(void) {
    static int buff = BMAX;
    if (buff == BMAX) {
        buff = 0;
        fread(buck, 1, BMAX, stdin); }
    return buck[ buff++ ]; }

void get(int &arg) {
    char ch;
    arg = 0;
    do {
        ch = nextch(); }
    while (ch < '0' || ch > '9');
    do {
        arg = arg * 10 + ch - '0';
        ch = nextch(); }
    while (ch >= '0' && ch <= '9'); }

int main(void) {
    freopen("tunel.in", "r", stdin);
    freopen("tunel.out", "w", stdout);
    int n, m, u, v, w;

    get(n), get(m);
    for (int i = 1; i <= m; ++i) {
        get(u), get(v), get(w);
        if (u != n) g[u].emplace_back(v, w);
        if (v != n) g[v].emplace_back(u, w); }

    for (int i = 1; i < n; ++i) {
        gs[i].resize(n + 2);
        for (const auto &j: g[i]) {
            gs[i][j.v]+= 1.0;
            gs[i][n + 1]+= j.w; }
        gs[i][i] = -int(g[i].size()); }
    gs[n].resize(n + 2);
    gs[n][n] = 1.0;

    for (int k, i = 1, j = 1; i <= n && j <= n; ++j) {
        if (eq(gs[i][j], 0.0)) {
            for (k = i; k <= n; ++k) {
                if (!eq(gs[k][j], 0.0)) {
                    swap(gs[i], gs[k]);
                    break; } }
            if (k > n)
                continue; }
        assert(!eq(gs[i][j], 0.0));
        for (k = 1; k <= n; ++k) if (k != i && !eq(gs[k][j], 0.0))
            gs[k]-= gs[i] * (gs[k][j] / gs[i][j]);
        ++i; }

    vals.resize(n + 1);
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            if(!eq(gs[i][j], 0.0))
                vals[j] = gs[i][n + 1] / gs[i][j];

    printf("%.4f\n", abs(vals[1])); // yep... I'm and idiot...

    return 0; }