Problem:
Problem E
Cost Performance Flow
Yayoi is a professional of money saving. Yayoi does not select items just because they are cheap; her motto is "cost performance". This is one of the reasons why she is good at cooking with bean sprouts. Due to her saving skill, Yayoi often receives requests to save various costs. This time, her task is optimization of "network flow".
Network flow is a problem on graph theory. Now, we consider a directed graph $G = (V, E)$, where $V = \{1, 2, ... , |V|\}$ is a vertex set and $E \subset V \times V$ is an edge set. Each edge $e$ in $E$ has a capacity $u(e)$ and a cost $c(e)$. For two vertices $s$ and $t$, a function $f_{s,t} : E \rightarrow R$, where $R$ is the set of real numbers, is called an $s$-$t$ flow if the following conditions hold:
For all $e$ in $E$, $f_{s,t}$ is non-negative and no more than $u(e)$. Namely, $0 \leq f_{s,t}(e) \leq u(e)$ holds.
For all $v$ in $V \setminus \{s, t\}$, the sum of $f_{s,t}$ of out-edges from $v$ equals the sum of $f_{s,t}$ of in-edges to $v$. Namely, $\sum_{e=(u,v) \in E} f_{s,t}(e) = \sum_{e=(v,w) \in E} f_{s,t}(e)$ holds.
Here, we define flow $F( f_{s,t})$ and cost $C( f_{s,t})$ of $f_{s,t}$ as $F( f_{s,t}) = \sum_{e=(s,v)\in E} f_{s,t}(e) - \sum_{e=(u,s)\in E} f_{s,t}(e)$ and $C( f_{s,t}) = \sum_{e\in E} f_{s,t}(e)c(e)$, respectively.
Usually, optimization of network flow is defined as cost minimization under the maximum flow. However, Yayoi's motto is "cost performance". She defines a balanced function $B( f_{s,t})$ for $s$-$t$ flow as the sum of the square of the cost $C( f_{s,t})$ and the difference between the maximum flow $M = max_{f : s-t flow} F( f )$ and the flow $F( f_{s,t})$, i.e. $B( f_{s,t}) = C( f_{s,t})^2 + (M - F( f_{s,t}))^2$. Then, Yayoi considers that the best cost performance flow yields the minimum of $B( f_{s,t})$.
Your task is to write a program for Yayoi calculating $B( f_{s,t}^*)$ for the best cost performance flow $f_{s,t}^*$.
Input
The input consists of a single test case. The first line gives two integers separated by a single space: the number of vertices $N$ $(2 \leq N \leq 100)$ and the number of edges $M$ $(1 \leq M \leq 1,000)$. The second line gives two integers separated by a single space: two vertices $s$ and $t$ $(1 \leq s, t \leq N, s \ne t)$. The $i$-th line of the following $M$ lines describes the $i$-th edges as four integers $a_i$, $b_i$, $u_i$, and $c_i$: the $i$-th edge from $a_i$ $(1 \leq a_i \leq N)$ to $b_i$ $(1 \leq b_i \leq N)$ has the capacity $u_i$ $(1 \leq u_i \leq 100)$ and the cost $c_i$ $(1 \leq c_i \leq 100)$ . You can assume that $a_i \ne b_i$ for all $1 \leq i \leq M$, and $a_i \ne a_j$ or $b_i \ne b_j$ if $i \ne j$ for all $1 \leq i, j \leq M$.
Output
Display $B( f_{s,t}^*)$, the minimum of balanced function under $s$-$t$ flow, as a fraction in a line. More precisely, output "$u/d$", where $u$ is the numerator and $d$ is the denominator of $B( f_{s,t}^*)$, respectively. Note that $u$ and
$d$ must be non-negative integ
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long INF = 10000000000;
const int INF2 = 10000;
struct bigint{
  bool neg;
  vector<int> d;
  bigint(){
    neg = false;
  }
  bigint(long long x){
    neg = x < 0;
    x = abs(x);
    while (x > 0){
      d.push_back(x % 10);
      x /= 10;
    }
    if (d.empty()){
      d.push_back(0);
    }
  }
  int operator [](int k){
    return d[k];
  }
  int size(){
    return d.size();
  }
};
ostream& operator <<(ostream& os, bigint x){
  if (x.neg){
    os << '-';
  }
  int N = x.size();
  for (int i = N - 1; i >= 0; i--){
    os << x[i];
  }
  return os;
}
bool operator ==(bigint A, bigint B){
  return A.neg == B.neg && A.d == B.d;
}
bool operator !=(bigint A, bigint B){
  return !(A == B);
}
bool operator <(bigint A, bigint B){
  if (A.neg && B.neg){
    A.neg = false;
    B.neg = false;
    return !(A < B);
  }
  if (A.neg){
    return true;
  }
  if (B.neg){
    return false;
  }
  int N1 = A.size();
  int N2 = B.size();
  if (N1 < N2){
    return true;
  }
  if (N1 > N2){
    return false;
  }
  for (int i = N1 - 1; i >= 0; i--){
    if (A[i] < B[i]){
      return true;
    }
    if (A[i] > B[i]){
      return false;
    }
  }
  return false;
}
bool operator <=(bigint A, bigint B){
  return A < B || A == B;
}
bigint operator -(bigint A){
  A.neg = !A.neg;
  return A;
}
bigint operator +(bigint A, bigint B);
bigint operator -(bigint A, bigint B);
bigint operator +(bigint A, bigint B){
  if (B.neg){
    return A - (-B);
  }
  if (A.neg){
    A.neg = false;
    if (B < A){
      return -(A - B);
    } else {
      return B - A;
    }
  }
  int N1 = A.size();
  int N2 = B.size();
  int N = max(N1, N2) + 1;
  bigint C;
  C.d = vector<int>(N, 0);
  for (int i = 0; i < N1; i++){
    C.d[i] += A[i];
  }
  for (int i = 0; i < N2; i++){
    C.d[i] += B[i];
  }
  for (int i = 0; i < N - 1; i++){
    if (C[i] >= 10){
      C.d[i + 1]++;
      C.d[i] -= 10;
    }
  }
  if (C.size() >= 2 && C[N - 1] == 0){
    C.d.pop_back();
  }
  return C;
}
bigint operator -(bigint A, bigint B){
  if (B.neg){
    return A + (-B);
  }
  if (A.neg){
    return -((-A) + B);
  }
  if (A < B){
    return -(B - A);
  }
  int N1 = A.size();
  int N2 = B.size();
  bigint C = A;
  for (int i = 0; i < N2; i++){
    C.d[i] -= B[i];
  }
  for (int i = 0; i < N1 - 1; i++){
    if (C[i] < 0){
      C.d[i + 1]--;
      C.d[i] += 10;
    }
  }
  while (C.size() >= 2 && C.d.back() == 0){
    C.d.pop_back();
  }
  return C;
}
bigint operator *(bigint A, bigint B){
  bool neg = A.neg ^ B.neg;
  int N1 = A.size();
  int N2 = B.size();
  int N = N1 + N2;
  bigint C;
  C.d = vector<int>(N, 0);
  for (int i = 0; i < N1; i++){
    for (int j = 0; j < N2; j++){
      C.d[i + j] += A[i] * B[j];
    }
  }
  for (int i = 0; i < N - 1; i++){
    C.d[i + 1] += C[i] / 10;
    C.d[i] %= 10;
  }
  while (C.size() >= 2 && C.d.back() == 0){
    C.d.pop_back();
  }
  if (C != 0 && neg){
    C.neg = true;
  }
  return C;
}
pair<bigint, bigint> divmod(bigint A, bigint B){
  int N1 = A.size();
  int N2 = B.size();
  bigint Q;
  for (int i = N1 - N2; i >= 0; i--){
  	int q = 0;
  	if (A.size() >= N2 + i){
  	  N1 = A.size();
      bigint C;
      C.d = vector<int>(N1 - i);
      for (int j = 0; j < N1 - i; j++){
        C.d[j] = A[i + j];
      }
      for (int j = 1; j <= 9; j++){
        if (B * j <= C){
          q = j;
        } else {
          break;
        }
      }
    }
    Q.d.push_back(q);
    bigint B2 = B * q;
    int M = B2.size();
    bigint B3;
    B3.d = vector<int>(M + i, 0);
    for (int j = 0; j < M; j++){
      B3.d[i + j] = B2[j];
    }
    while (B3.size() >= 2 && B3.d.back() == 0){
      B3.d.pop_back();
    }
    A = A - B3;
  }
  if (Q.size() == 0){
    Q.d.push_back(0);
  }
  reverse(Q.d.begin(), Q.d.end());
  if (Q.size() >= 2 && Q.d.back() == 0){
    Q.d.pop_back();
  }
  return make_pair(Q, A);
}
bigint operator /(bigint A, bigint B){
  return divmod(A, B).first;
}
bigint operator %(bigint A, bigint B){
  return divmod(A, B).second;
}
bigint gcd(bigint x, bigint y){
  if (y == 0){
    return x;
  } else {
    return gcd(y, x % y);
  }
}
struct bigfrac{
  bigint num, den;
  bigfrac(long long x): num(x), den(1){
  }
  bigfrac(bigint x, bigint y = 1){
    bool neg = x.neg ^ y.neg;
    x.neg = false;
    y.neg = false;
    bigint g = gcd(x, y);
    num = x / g;
    den = y / g;
    if (neg){
      num.neg = true;
    }
  }
};
bool operator <(bigfrac a, bigfrac b){
  return a.num * b.den < b.num * a.den;
}
bigfrac operator +(bigfrac a, bigfrac b){
  return bigfrac(a.num * b.den + b.num * a.den, a.den * b.den);
}
bigfrac operator *(bigfrac a, bigfrac b){
  return bigfrac(a.num * b.num, a.den * b.den);
}
struct primal_dual{
  struct edge{
    int to, rev, cap, cost;
    edge(int to, int rev, int cap, int cost): to(to), rev(rev), cap(cap), cost(cost){
    }
  };
  int N;
  vector<vector<edge>> G;
  primal_dual(int N): N(N), G(N){
  }
  void add_edge(int from, int to, int cap, int cost){
    G[from].push_back(edge(to, G[to].size(), cap, cost));
    G[to].push_back(edge(from, G[from].size() - 1, 0, -cost));
  }
  vector<pair<bigint, bigint>> min_cost_slope(int s, int t){
    vector<pair<bigint, bigint>> ans;
    ans.push_back(make_pair(0, 0));
    int flow = 0, cost = 0;
    vector<int> h(N, 0);
    while (true){
      vector<int> m(N, INF2);
      vector<int> d(N, INF2);
      vector<int> pv(N, -1);
      vector<int> pe(N, -1);
      vector<bool> used(N, false);
      priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
      pq.push(make_pair(0, s));
      d[s] = 0;
      while (!pq.empty()){
        int v = pq.top().second;
        pq.pop();
        if (!used[v]){
          used[v] = true;
          int cnt = G[v].size();
          for (int i = 0; i < cnt; i++){
            int w = G[v][i].to;
            if (!used[w] && G[v][i].cap > 0){
              int tmp = d[v] + G[v][i].cost - h[w] + h[v];
              if (d[w] > tmp){
                d[w] = tmp;
                m[w] = min(m[v], G[v][i].cap);
                pv[w] = v;
                pe[w] = i;
                pq.push(make_pair(d[w], w));
              }
            }
          }
        }
      }
      if (!used[t]){
        break;
      } else {
        for (int i = 0; i < N; i++){
          if (used[i]){
            h[i] -= d[t] - d[i];
          }
        }
        int f = m[t];
        for (int v = t; v != s; v = pv[v]){
          G[pv[v]][pe[v]].cap -= f;
          G[v][G[pv[v]][pe[v]].rev].cap += f;
        }
        flow += f;
        cost += f * -h[s];
        ans.push_back(make_pair(flow, cost));
      }
    }
    return ans;
  }
};
int main(){
  int N, M;
  cin >> N >> M;
  int s, t;
  cin >> s >> t;
  s--;
  t--;
  primal_dual G(N);
  for (int i = 0; i < M; i++){
    int a, b, u, c;
    cin >> a >> b >> u >> c;
    a--;
    b--;
    G.add_edge(a, b, u, c);
  }
  vector<pair<bigint, bigint>> ans = G.min_cost_slope(s, t);
  int cnt = ans.size();
  if (cnt == 1){
    cout << "0/1" << endl;
  } else {
    bigint mx = ans.back().first;
    bigfrac mn = INF;
    for (int i = 0; i < cnt - 1; i++){
      bigint L = ans[i].first;
      bigint R = ans[i + 1].first;
      bigint a = (ans[i + 1].second - ans[i].second) / (R - L);
      bigint b = ans[i].second - ans[i].first * a;
      bigint A = a * a + 1;
      bigint B = 2 * a * b - 2 * mx;
      bigint C = b * b + mx * mx;
      bigfrac x(-B, A * 2);
      if (x < L){
        x = L;
      }
      if (R < x){
        x = R;
      }
      bigfrac y = A * x * x + B * x + C;
      if (y < mn){
        mn = y;
      }
    }
    cout << mn.num << "/" << mn.den << endl;
  }
}
accuracy: 1
time_ms: 40
memory_kb: 3288
final_rank: 2

code_snippet: #include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <limits>

template <class Cap, class Cost>
struct MinCostFlow {
    struct Edge {
        int src, dst;
        Cap cap;
        Cost cost;
        Edge(int src, int dst, Cap cap, Cost cost)
            : src(src), dst(dst), cap(cap), cost(cost){};
    };

    std::vector<Edge> edges;
    std::vector<std::vector<int>> graph;

    std::vector<Cost> dist;
    std::vector<int> rev;

    const Cost INF = std::numeric_limits<Cost>::max() / 2;

    explicit MinCostFlow(int n) : graph(n), dist(n), rev(n) {}

    void span(int u, int v, Cap cap, Cost cost) {
        graph[u].push_back(edges.size());
        edges.emplace_back(u, v, cap, cost);

        graph[v].push_back(edges.size());
        edges.emplace_back(v, u, 0, -cost);
    }

    void bellman_ford(int s) {
        std::fill(dist.begin(), dist.end(), INF);
        dist[s] = 0;

        bool update = true;
        while (update) {
            update = false;

            for (int eidx = 0; eidx < (int)edges.size(); ++eidx) {
                const auto& edge = edges[eidx];
                int u = edge.src, v = edge.dst;

                if (edge.cap > 0 && dist[u] < INF &&
                    dist[v] > dist[u] + edge.cost) {
                    dist[v] = dist[u] + edge.cost;
                    rev[v] = eidx;
                    update = true;
                }
            }
        }
    }

    std::pair<Cap, Cost> flow(int s, int g, Cap flow_limit) {
        Cap fsum = 0;
        Cost csum = 0;

        while (flow_limit > 0) {
            bellman_ford(s);
            if (dist[g] == INF) break;

            Cap f = flow_limit;
            int v = g;
            while (v != s) {
                const auto& edge = edges[rev[v]];
                f = std::min(f, edge.cap);
                v = edge.src;
            }

            flow_limit -= f;
            fsum += f;
            csum += f * dist[g];

            v = g;
            while (v != s) {
                auto& edge = edges[rev[v]];
                auto& redge = edges[rev[v] ^ 1];
                edge.cap -= f;
                redge.cap += f;
                v = edge.src;
            }
        }
        return {fsum, csum};
    }

    std::pair<Cap, Cost> flow(int s, int g) {
        return flow(s, g, std::numeric_limits<Cap>::max());
    }
};

using namespace std;
using lint = long long;

struct R {
    lint x, y;  // x/y

    void normalize() {
        if (y < 0) x = -x, y = -y;
        auto g = gcd(x, y);
        x /= g, y /= g;
    }

    R(lint x, lint y = 1) : x(x), y(y) { normalize(); }

    R operator+(const R& other) const {
        auto ny = lcm(y, other.y);
        return R(x * (ny / y) + other.x * (ny / other.y), ny);
    }
    R operator-(const R& other) const {
        auto ny = lcm(y, other.y);
        return R(x * (ny / y) - other.x * (ny / other.y), ny);
    }
    R operator*(const R& other) const {
        auto g0 = gcd(x, other.y);
        auto g1 = gcd(y, other.x);
        return R((x / g0) * (other.x / g1),
                 (y / g1) * (other.y / g0));
    }

    bool operator<(const R& other) const {
        return __int128(x) * other.y < __int128(y) * other.x;
    }
};

template <class T>
T sq(const T& x) { return x * x; }

void solve() {
    int n, m, s, g;
    cin >> n >> m >> s >> g;
    --s, --g;

    MinCostFlow<lint, lint> mcf(n);
    while (m--) {
        int u, v, p, c;
        cin >> u >> v >> p >> c;
        mcf.span(--u, --v, p, c);
    }

    vector<lint> fs{0};
    while (true) {
        auto [f, c] = mcf.flow(s, g, 1);
        if (f == 0) break;
        fs.push_back(fs.back() + c);
    }

    m = fs.size() - 1;
    R ans = sq(m);

    for (lint x = 0; x < m; ++x) {
        lint a = fs[x + 1] - fs[x];
        lint b = fs[x] - a * x;

        for (int d = 0; d <= 1; ++d) {
            lint nx = x + d;
            ans = min(ans, R(sq(m - nx) + sq(nx * a + b)));
        }

        R mx(m - a * b, a * a + 1);
        if (mx.x < 0 || mx < x || R(x + 1) < mx) continue;
        ans = min(ans, R(m * m + b * b) - mx * (m - a * b));
    }

    cout << ans.x << "/" << ans.y << "\n";
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3572
final_rank: 6

code_snippet: #include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <limits>

template <class Cap, class Cost>
struct MinCostFlow {
    struct Edge {
        int src, dst;
        Cap cap;
        Cost cost;
        Edge(int src, int dst, Cap cap, Cost cost)
            : src(src), dst(dst), cap(cap), cost(cost){};
    };

    std::vector<Edge> edges;
    std::vector<std::vector<int>> graph;

    std::vector<Cost> dist;
    std::vector<int> rev;

    const Cost INF = std::numeric_limits<Cost>::max() / 2;

    explicit MinCostFlow(int n) : graph(n), dist(n), rev(n) {}

    void span(int u, int v, Cap cap, Cost cost) {
        graph[u].push_back(edges.size());
        edges.emplace_back(u, v, cap, cost);

        graph[v].push_back(edges.size());
        edges.emplace_back(v, u, 0, -cost);
    }

    void bellman_ford(int s) {
        std::fill(dist.begin(), dist.end(), INF);
        dist[s] = 0;

        bool update = true;
        while (update) {
            update = false;

            for (int eidx = 0; eidx < (int)edges.size(); ++eidx) {
                const auto& edge = edges[eidx];
                int u = edge.src, v = edge.dst;

                if (edge.cap > 0 && dist[u] < INF &&
                    dist[v] > dist[u] + edge.cost) {
                    dist[v] = dist[u] + edge.cost;
                    rev[v] = eidx;
                    update = true;
                }
            }
        }
    }

    std::pair<Cap, Cost> flow(int s, int g, Cap flow_limit) {
        Cap fsum = 0;
        Cost csum = 0;

        while (flow_limit > 0) {
            bellman_ford(s);
            if (dist[g] == INF) break;

            Cap f = flow_limit;
            int v = g;
            while (v != s) {
                const auto& edge = edges[rev[v]];
                f = std::min(f, edge.cap);
                v = edge.src;
            }

            flow_limit -= f;
            fsum += f;
            csum += f * dist[g];

            v = g;
            while (v != s) {
                auto& edge = edges[rev[v]];
                auto& redge = edges[rev[v] ^ 1];
                edge.cap -= f;
                redge.cap += f;
                v = edge.src;
            }
        }
        return {fsum, csum};
    }

    std::pair<Cap, Cost> flow(int s, int g) {
        return flow(s, g, std::numeric_limits<Cap>::max());
    }
};

using namespace std;
using lint = long long;
constexpr lint INF = 1LL << 60;

struct R {
    lint x, y;  // x/y

    void normalize() {
        if (y < 0) x = -x, y = -y;
        lint g = gcd(x, y);
        x /= g, y /= g;
    }

    R(lint x, lint y = 1) : x(x), y(y) { normalize(); }

    R operator+(const R& other) const {
        lint ny = lcm(y, other.y);
        return R(x * (ny / y) + other.x * (ny / other.y), ny);
    }
    R operator-(const R& other) const {
        lint ny = lcm(y, other.y);
        return R(x * (ny / y) - other.x * (ny / other.y), ny);
    }
    R operator*(const R& other) const {
        auto g0 = gcd(x, other.y);
        auto g1 = gcd(y, other.x);
        return R((x / g0) * (other.x / g1),
                 (y / g1) * (other.y / g0));
    }

    bool operator<(const R& other) const {
        return __int128(x) * other.y < __int128(y) * other.x;
    }
};

template <class T>
T sq(const T& x) { return x * x; }

void solve() {
    int n, m, s, g;
    cin >> n >> m >> s >> g;
    --s, --g;

    MinCostFlow<lint, lint> mcf(n);
    while (m--) {
        int u, v, p, c;
        cin >> u >> v >> p >> c;
        mcf.span(--u, --v, p, c);
    }

    vector<lint> fs{0};
    while (true) {
        auto [f, c] = mcf.flow(s, g, 1);
        if (f == 0) break;
        fs.push_back(fs.back() + c);
    }

    m = fs.size() - 1;
    R ans = sq(m);

    for (lint x = 0; x < m; ++x) {
        lint a = fs[x + 1] - fs[x];
        lint b = fs[x] - a * x;

        for (int d = 0; d <= 1; ++d) {
            lint nx = x + d;
            ans = min(ans, R(sq(m - nx) + sq(nx * a + b)));
        }

        R mx(m - a * b, a * a + 1);
        if (mx < x || R(x + 1) < mx) continue;
        ans = min(ans, sq(R(m) - mx) + sq(mx * a + b));
    }

    cout << ans.x << "/" << ans.y << "\n";
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 0.9775280898876404
time_ms: 10
memory_kb: 3572
final_rank: 10

code_snippet: #include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <limits>

template <class Cap, class Cost>
struct MinCostFlow {
    struct Edge {
        int src, dst;
        Cap cap;
        Cost cost;
        Edge(int src, int dst, Cap cap, Cost cost)
            : src(src), dst(dst), cap(cap), cost(cost){};
    };

    std::vector<Edge> edges;
    std::vector<std::vector<int>> graph;

    std::vector<Cost> dist;
    std::vector<int> rev;

    const Cost INF = std::numeric_limits<Cost>::max() / 2;

    explicit MinCostFlow(int n) : graph(n), dist(n), rev(n) {}

    void span(int u, int v, Cap cap, Cost cost) {
        graph[u].push_back(edges.size());
        edges.emplace_back(u, v, cap, cost);

        graph[v].push_back(edges.size());
        edges.emplace_back(v, u, 0, -cost);
    }

    void bellman_ford(int s) {
        std::fill(dist.begin(), dist.end(), INF);
        dist[s] = 0;

        bool update = true;
        while (update) {
            update = false;

            for (int eidx = 0; eidx < (int)edges.size(); ++eidx) {
                const auto& edge = edges[eidx];
                int u = edge.src, v = edge.dst;

                if (edge.cap > 0 && dist[u] < INF &&
                    dist[v] > dist[u] + edge.cost) {
                    dist[v] = dist[u] + edge.cost;
                    rev[v] = eidx;
                    update = true;
                }
            }
        }
    }

    std::pair<Cap, Cost> flow(int s, int g, Cap flow_limit) {
        Cap fsum = 0;
        Cost csum = 0;

        while (flow_limit > 0) {
            bellman_ford(s);
            if (dist[g] == INF) break;

            Cap f = flow_limit;
            int v = g;
            while (v != s) {
                const auto& edge = edges[rev[v]];
                f = std::min(f, edge.cap);
                v = edge.src;
            }

            flow_limit -= f;
            fsum += f;
            csum += f * dist[g];

            v = g;
            while (v != s) {
                auto& edge = edges[rev[v]];
                auto& redge = edges[rev[v] ^ 1];
                edge.cap -= f;
                redge.cap += f;
                v = edge.src;
            }
        }
        return {fsum, csum};
    }

    std::pair<Cap, Cost> flow(int s, int g) {
        return flow(s, g, std::numeric_limits<Cap>::max());
    }
};

using namespace std;
using lint = long long;
constexpr lint INF = 1LL << 60;

struct R {
    lint x, y;  // x/y

    void normalize() {
        if (y < 0) x = -x, y = -y;
        lint g = gcd(x, y);
        x /= g, y /= g;
    }

    R(lint x, lint y = 1) : x(x), y(y) { normalize(); }

    R operator+(const R& other) const {
        return R(x * other.y + other.x * y, y * other.y);
    }
    R operator-(const R& other) const {
        return R(x * other.y - other.x * y, y * other.y);
    }
    R operator*(const R& other) const {
        return R(x * other.x, y * other.y);
    }

    bool operator<(const R& other) const { return x * other.y < other.x * y; }
};

template <class T>
T sq(const T& x) { return x * x; }

void solve() {
    int n, m, s, g;
    cin >> n >> m >> s >> g;
    --s, --g;

    MinCostFlow<lint, lint> mcf(n);
    while (m--) {
        int u, v, p, c;
        cin >> u >> v >> p >> c;
        mcf.span(--u, --v, p, c);
    }

    vector<lint> fs{0};
    while (true) {
        auto [f, c] = mcf.flow(s, g, 1);
        if (f == 0) break;
        fs.push_back(fs.back() + c);
    }

    m = fs.size() - 1;
    R ans = sq(m);

    for (lint x = 0; x < m; ++x) {
        lint a = fs[x + 1] - fs[x];
        lint b = fs[x] - a * x;

        for (int d = 0; d <= 1; ++d) {
            lint nx = x + d;
            ans = min(ans, R(sq(m - nx) + sq(nx * a + b)));
        }

        R mx(m - a * b, a * a + 1);
        if (mx < x || R(x + 1) < mx) continue;
        ans = min(ans, sq(R(m) - mx) + sq(mx * a + b));
    }

    cout << ans.x << "/" << ans.y << "\n";
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 0.9662921348314607
time_ms: 10
memory_kb: 3572
final_rank: 13

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
const int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

template <typename T>
struct Dinic {
  struct Edge {
    int dst, rev;
    T cap;
    Edge(int dst, T cap, int rev) : dst(dst), cap(cap), rev(rev) {}
  };

  vector<vector<Edge> > graph;

  Dinic(int n) : graph(n), level(n), itr(n) {}

  void add_edge(int src, int dst, T cap) {
    graph[src].emplace_back(dst, cap, graph[dst].size());
    graph[dst].emplace_back(src, 0, graph[src].size() - 1);
  }

  T maximum_flow(int s, int t, T limit) {
    T res = 0;
    while (true) {
      bfs(s);
      if (level[t] == -1) return res;
      fill(ALL(itr), 0);
      T tmp;
      while ((tmp = dfs(s, t, limit)) > 0) res += tmp;
    }
  }

private:
  vector<int> level, itr;

  void bfs(int s) {
    fill(ALL(level), -1);
    queue<int> que;
    level[s] = 0;
    que.emplace(s);
    while (!que.empty()) {
      int ver = que.front(); que.pop();
      for (const Edge &e : graph[ver]) {
        if (level[e.dst] == -1 && e.cap > 0) {
          level[e.dst] = level[ver] + 1;
          que.emplace(e.dst);
        }
      }
    }
  }

  T dfs(int ver, int t, T flow) {
    if (ver == t) return flow;
    for (; itr[ver] < graph[ver].size(); ++itr[ver]) {
      Edge &e = graph[ver][itr[ver]];
      if (level[ver] < level[e.dst] && e.cap > 0) {
        T tmp = dfs(e.dst, t, min(flow, e.cap));
        if (tmp > 0) {
          e.cap -= tmp;
          graph[e.dst][e.rev].cap += tmp;
          return tmp;
        }
      }
    }
    return 0;
  }
};

template <typename T, typename U>
struct PrimalDual {
  using Pui = pair<U, int>;

  struct Edge {
    int dst, rev;
    T cap;
    U cost;
    Edge(int dst, T cap, U cost, int rev) : dst(dst), cap(cap), cost(cost), rev(rev) {}
  };

  vector<vector<Edge> > graph;

  PrimalDual(int n, const T TINF, const U UINF) : n(n), TINF(TINF), UINF(UINF), graph(n), prev_v(n, -1), prev_e(n, -1), potential(n, 0), dist(n) {}

  void add_edge(int src, int dst, T cap, U cost) {
    has_negative_edge |= cost < 0;
    graph[src].emplace_back(dst, cap, cost, graph[dst].size());
    graph[dst].emplace_back(src, 0, -cost, graph[src].size() - 1);
  }

  U minimum_cost_flow(int s, int t, T flow) {
    U res = 0;
    if (has_negative_edge) {
      bellman_ford(s);
      if (dist[t] == UINF) return UINF;
      res += calc(s, t, flow);
    }
    while (flow > 0) {
      dijkstra(s);
      if (dist[t] == UINF) return UINF;
      res += calc(s, t, flow);
    }
    return res;
  }

  U minimum_cost_flow(int s, int t) {
    U res = 0;
    bellman_ford(s);
    if (potential[t] >= 0 || dist[t] == UINF) return res;
    T tmp = TINF;
    res += calc(s, t, tmp);
    while (true) {
      dijkstra(s);
      if (potential[t] >= 0 || dist[t] == UINF) return res;
      res += calc(s, t, tmp);
    }
  }

  pair<T, U> min_cost_max_flow(int s, int t, T flow) {
    T mx = flow;
    U cost = 0;
    if (has_negative_edge) {
      bellman_ford(s);
      if (dist[t] == UINF) return {mx - flow, cost};
      cost += calc(s, t, flow);
    }
    while (flow > 0) {
      dijkstra(s);
      if (dist[t] == UINF) return {mx - flow, cost};
      cost += calc(s, t, flow);
    }
    return {mx - flow, cost};
  }

// private:
  int n;
  const T TINF;
  const U UINF;
  bool has_negative_edge = false;
  vector<int> prev_v, prev_e;
  vector<U> potential, dist;
  priority_queue<Pui, vector<Pui>, greater<Pui> > que;

  void bellman_ford(int s) {
    fill(ALL(dist), UINF);
    dist[s] = 0;
    bool is_updated = true;
    REP(step, n) {
      is_updated = false;
      REP(i, n) if (dist[i] != UINF) {
        REP(j, graph[i].size()) {
          Edge e = graph[i][j];
          if (e.cap > 0 && dist[e.dst] > dist[i] + e.cost) {
            dist[e.dst] = dist[i] + e.cost;
            prev_v[e.dst] = i;
            prev_e[e.dst] = j;
            is_updated = true;
          }
        }
      }
      if (!is_updated) break;
    }
    assert(!is_updated);
    REP(i, n) {
      if (dist[i] != UINF) potential[i] += dist[i];
    }
  }

  void dijkstra(int s) {
    fill(ALL(dist), UINF);
    dist[s] = 0;
    que.emplace(0, s);
    while (!que.empty()) {
      Pui pr = que.top(); que.pop();
      int ver = pr.second;
      if (dist[ver] < pr.first) continue;
      REP(i, graph[ver].size()) {
        Edge e = graph[ver][i];
        U nx = dist[ver] + e.cost + potential[ver] - potential[e.dst];
        if (e.cap > 0 && dist[e.dst] > nx) {
          dist[e.dst] = nx;
          prev_v[e.dst] = ver;
          prev_e[e.dst] = i;
          que.emplace(dist[e.dst], e.dst);
        }
      }
    }
    REP(i, n) {
      if (dist[i] != UINF) potential[i] += dist[i];
    }
  }

  U calc(int s, int t, T &flow) {
    T f = flow;
    for (int v = t; v != s; v = prev_v[v]) f = min(f, graph[prev_v[v]][prev_e[v]].cap);
    flow -= f;
    for (int v = t; v != s; v = prev_v[v]) {
      Edge &e = graph[prev_v[v]][prev_e[v]];
      e.cap -= f;
      graph[v][e.rev].cap += f;
    }
    return potential[t] * f;
  }
};

template <typename T = ll>
struct Rational {
  T num, den;
  Rational(): num(0), den(1) {}
  Rational(T num_, T den_ = 1) : num(num_), den(den_) { assert(den != 0); reduce(); }
  template <typename Real = long double> Real to_real() { return (Real)num / den; }
  Rational &operator+=(const Rational &x) {
    T g = __gcd(den, x.den);
    num = num * (x.den / g) + x.num * (den / g); den *= x.den / g;
    reduce();
    return *this;
  }
  Rational &operator-=(const Rational &x) { return *this += -x; }
  Rational &operator*=(const Rational &x) {
    T g1 = __gcd(num, x.den), g2 = __gcd(den, x.num);
    num = (num / g1) * (x.num / g2); den = (den / g2) * (x.den / g1);
    reduce();
    return *this;
  }
  Rational &operator/=(const Rational &x) { return *this *= Rational(x.den, x.num); }
  bool operator==(const Rational &x) const { return num == x.num && den == x.den; }
  bool operator!=(const Rational &x) const { return !(*this == x); }
  bool operator<(const Rational &x) const { return (x - *this).num > 0; }
  bool operator<=(const Rational &x) const { return !(x < *this); }
  bool operator>(const Rational &x) const { return x < *this; }
  bool operator>=(const Rational &x) const { return !(*this < x); }
  Rational &operator++() { if ((num += den) == 0) den = 1; return *this; }
  Rational operator++(int) { Rational res = *this; ++*this; return res; }
  Rational &operator--() { if ((num -= den) == 0) den = 1; return *this; }
  Rational operator--(int) { Rational res = *this; --*this; return res; }
  Rational operator+() const { return *this; }
  Rational operator-() const { return Rational(-num, den); }
  Rational operator+(const Rational &x) const { return Rational(*this) += x; }
  Rational operator-(const Rational &x) const { return Rational(*this) -= x; }
  Rational operator*(const Rational &x) const { return Rational(*this) *= x; }
  Rational operator/(const Rational &x) const { return Rational(*this) /= x; }
  friend ostream &operator<<(ostream &os, const Rational &x) {
    if (x.den == 1) return os << x.num;
    return os << x.num << '/' << x.den;
  }
private:
  void reduce() { T g = __gcd(num, den); num /= g; den /= g; if (den < 0) { num = -num; den = -den; } }
};
template <typename T> Rational<T> abs(const Rational<T> &x) {Rational<T> res = x; if (res.num < 0) res.num = -res.num; return res; }
template <typename T> Rational<T> max(const Rational<T> &a, const Rational<T> &b) { return a < b ? b : a; }
template <typename T> Rational<T> min(const Rational<T> &a, const Rational<T> &b) { return a < b ? a : b; }

const int LG10_BASE = 9, BASE = 1000000000; // BASE = 10^{LG_10BASE}
struct BigInt {
  int sign; vector<int> dat;
  BigInt(ll val = 0) { *this = val; }
  BigInt(const string &s) { *this = s; }
  vector<ll> convert_base(int new_lg10_base, int new_base) const {
    // assert(new_base == static_cast<int>(round(pow(10, new_lg10_base))));
    int mx_base = max(LG10_BASE, new_lg10_base);
    vector<ll> p(mx_base + 1, 1);
    FOR(i, 1, mx_base + 1) p[i] = p[i - 1] * 10;
    vector<ll> res;
    ll now_val = 0;
    int now_lg10_base = 0;
    for (int e : dat) {
      now_val += p[now_lg10_base] * e;
      now_lg10_base += LG10_BASE;
      while (now_lg10_base >= new_lg10_base) {
        res.emplace_back(now_val % new_base);
        now_val /= new_base;
        now_lg10_base -= new_lg10_base;
      }
    }
    res.emplace_back(now_val);
    while (!res.empty() && res.back() == 0) res.pop_back();
    return res;
  }
  int digit_sum() {
    assert(sign == 1);
    string s = to_string();
    int res = 0;
    for (char c : s) res += c - '0';
    return res;
  }
  int length() {
    if (dat.empty()) return 0;
    int res = LG10_BASE * (dat.size() - 1);
    int tmp = dat.back();
    while (tmp > 0) { ++res; tmp /= 10; }
    return res;
  }
  BigInt pow(BigInt exponent) {
    BigInt res = 1, tmp = *this;
    while (exponent > 0) {
      if (exponent.dat[0] & 1) res *= tmp;
      tmp *= tmp;
      exponent /= 2;
    }
    return res;
  }
  ll to_llong() const {
    assert(*this >= LLONG_MIN && *this <= LLONG_MAX);
    ll res = 0;
    for (int i = static_cast<int>(dat.size()) - 1; i >= 0; --i) (res *= BASE) += dat[i];
    return res;
  }
  string to_string() { stringstream ss; ss << *this; string res; ss >> res; return res; }
  void trim() {
    while (!dat.empty() && dat.back() == 0) dat.pop_back();
    if (dat.empty()) sign = 1;
  }
  BigInt &operator=(ll val) {
    sign = 1;
    if (val < 0) { sign = -1; val = -val;}
    dat.clear();
    for (; val > 0; val /= BASE) dat.emplace_back(val % BASE);
    return *this;
  }
  BigInt &operator=(const string &s) {
    sign = 1;
    dat.clear();
    if (!s.empty()) {
      int tail = 0;
      if (s[tail] == '-' || s[tail] == '+') {
        if (s[tail] == '-') sign = -1;
        ++tail;
      }
      for (int i = s.length() - 1; i >= tail; i -= LG10_BASE) {
        int val = 0;
        for (int j = max(tail, i - LG10_BASE + 1); j <= i; ++j) val = val * 10 + (s[j] - '0');
        dat.emplace_back(val);
      }
    }
    trim();
    return *this;
  }
  BigInt &operator=(const BigInt &x) {
    sign = x.sign;
    dat.resize(x.dat.size());
    copy(ALL(x.dat), dat.begin());
    return *this;
  }
  BigInt &operator+=(const BigInt &x) {
    if (sign == x.sign) {
      bool carry = false;
      for (int i = 0; i < max(dat.size(), x.dat.size()) || carry; ++i) {
        if (i == dat.size()) dat.emplace_back(0);
        dat[i] += (i < x.dat.size() ? x.dat[i] : 0) + carry;
        carry = dat[i] >= BASE;
        if (carry) dat[i] -= BASE;
      }
    } else {
      *this -= -x;
    }
    return *this;
  }
  BigInt &operator-=(const BigInt &x) {
    if (sign == x.sign) {
      BigInt abs_this = *this, abs_x = x;
      abs_this.sign = 1; abs_x.sign = 1;
      if (abs_this >= abs_x) {
        bool carry = false;
        for (int i = 0; i < dat.size() || carry; ++i) {
          dat[i] -= (i < x.dat.size() ? x.dat[i] : 0) + carry;
          carry = dat[i] < 0;
          if (carry) dat[i] += BASE;
        }
        trim();
      } else {
        *this = -(x - *this);
      }
    } else {
      *this += -x;
    }
    return *this;
  }
  BigInt &operator*=(const BigInt &x) {
    const int new_log10_base = 6, new_base = 1000000;
    vector<ll> this6 = convert_base(new_log10_base, new_base), x6 = x.convert_base(new_log10_base, new_base);
    vector<ll> res = karatsuba(this6, 0, this6.size(), x6, 0, x6.size());
    REP(i, res.size()) {
      ll quo = res[i] / new_base;
      if (quo > 0) {
        if (i + 1 == res.size()) res.emplace_back(0);
        res[i + 1] += quo;
      }
      res[i] %= new_base;
    }
    string s = (sign * x.sign == 1 ? "+" : "-");
    for (int i = static_cast<int>(res.size()) - 1; i >= 0; --i) {
      string tmp = std::to_string(res[i]);
      REP(_, new_log10_base - tmp.size()) s += '0';
      s += tmp;
    }
    return *this = s;
  }
  BigInt &operator/=(int x) { return *this = divide(x).first; }
  BigInt &operator/=(const BigInt &x) { return *this = divide(x).first; }
  BigInt &operator%=(int x) { return *this = divide(x).second; }
  BigInt &operator%=(const BigInt &x) { return *this = divide(x).second; }
  bool operator==(const BigInt &x) const {
    if (sign != x.sign || dat.size() != x.dat.size()) return false;
    int sz = dat.size();
    REP(i, sz) if (dat[i] != x.dat[i]) return false;
    return true;
  }
  bool operator!=(const BigInt &x) const { return !(*this == x); }
  bool operator<(const BigInt &x) const {
    if (sign != x.sign) return sign < x.sign;
    if (dat.size() != x.dat.size()) return sign * dat.size() < x.sign * x.dat.size();
    for (int i = static_cast<int>(dat.size()) - 1; i >= 0; --i) {
      if (dat[i] != x.dat[i]) return dat[i] * sign < x.dat[i] * x.sign;
    }
    return false;
  }
  bool operator<=(const BigInt &x) const { return !(x < *this); }
  bool operator>(const BigInt &x) const { return x < *this; }
  bool operator>=(const BigInt &x) const { return !(*this < x); }
  BigInt &operator++() { return *this += 1; }
  BigInt operator++(int) { BigInt res = *this; ++*this; return res; }
  BigInt &operator--() { return *this -= 1; }
  BigInt operator--(int) { BigInt res = *this; --*this; return res; }
  BigInt operator+() const { return *this; }
  BigInt operator-() const { BigInt res = *this; res.sign = -res.sign; return res; }
  BigInt operator+(const BigInt &x) const { return BigInt(*this) += x; }
  BigInt operator-(const BigInt &x) const { return BigInt(*this) -= x; }
  BigInt operator*(const BigInt &x) const { return BigInt(*this) *= x; }
  BigInt operator/(int x) const { return BigInt(*this) /= x; }
  BigInt operator/(const BigInt &x) const { return BigInt(*this) /= x; }
  BigInt operator%(int x) const { return BigInt(*this) %= x; }
  BigInt operator%(const BigInt &x) const { return BigInt(*this) %= x; }
  friend ostream &operator<<(ostream &os, const BigInt &x) {
    if (x.sign == -1) os << '-';
    os << (x.dat.empty() ? 0 : x.dat.back());
    for (int i = static_cast<int>(x.dat.size()) - 2; i >= 0; --i) os << setw(LG10_BASE) << setfill('0') << x.dat[i];
    return os;
  }
  friend istream &operator>>(istream &is, BigInt &x) { string s; is >> s; x = s; return is; }
private:
  vector<ll> karatsuba(vector<ll> &a, int a_l, int a_r, vector<ll> &b, int b_l, int b_r) {
    int a_len = a_r - a_l, b_len = b_r - b_l;
    if (a_len < b_len) return karatsuba(b, b_l, b_r, a, a_l, a_r);
    vector<ll> res(a_len + b_len, 0);
    if (b_len <= 32) {
      FOR(i, a_l, a_r) FOR(j, b_l, b_r) res[(i - a_l) + (j - b_l)] += a[i] * b[j];
    } else {
      int mid = (a_len + 1) / 2, n = min(a_len, mid);
      for (int i = a_l; i + mid < a_r; ++i) a[i] += a[i + mid];
      for (int i = b_l; i + mid < b_r; ++i) b[i] += b[i + mid];
      vector<ll> tmp = karatsuba(a, a_l, a_l + mid, b, b_l, b_l + n);
      REP(i, tmp.size()) res[mid + i] = tmp[i];
      for (int i = a_l; i + mid < a_r; ++i) a[i] -= a[i + mid];
      for (int i = b_l; i + mid < b_r; ++i) b[i] -= b[i + mid];
      tmp = karatsuba(a, a_l, a_l + mid, b, b_l, b_l + n);
      REP(i, tmp.size()) { res[i] += tmp[i]; res[mid + i] -= tmp[i]; }
      tmp = karatsuba(a, a_l + mid, a_r, b, b_l + n, b_r);
      REP(i, tmp.size()) { res[mid + i] -= tmp[i]; res[(mid << 1) + i] += tmp[i]; }
    }
    while (!res.empty() && res.back() == 0) res.pop_back();
    return res;
  }
  pair<BigInt, int> divide(int x) {
    // assert(!x.dat.empty());
    BigInt dividend = *this;
    if (x < 0) { dividend.sign = -dividend.sign; x = -x; }
    ll rem = 0;
    for (int i = static_cast<int>(dividend.dat.size()) - 1; i >= 0; --i) {
      ll tmp = rem * BASE + dividend.dat[i];
      dividend.dat[i] = static_cast<int>(tmp / x);
      rem = tmp % x;
    }
    dividend.trim();
    return {dividend, static_cast<int>(rem)};
  }
  pair<BigInt, BigInt> divide(const BigInt &x) {
    // assert(!x.dat.empty());
    int k = BASE / (x.dat.back() + 1);
    BigInt dividend = *this, divisor = x;
    dividend.sign = 1; divisor.sign = 1;
    dividend *= k; divisor *= k;
    BigInt quo, rem = 0;
    quo.dat.resize(dividend.dat.size());
    int sz = divisor.dat.size();
    for (int i = static_cast<int>(dividend.dat.size()) - 1; i >= 0; --i) {
      rem.dat.insert(rem.dat.begin(), dividend.dat[i]);
      quo.dat[i] = static_cast<int>(((sz < rem.dat.size() ? 1LL * rem.dat[sz] * BASE : 0) + (sz - 1 < rem.dat.size() ? rem.dat[sz - 1] : 0)) / divisor.dat.back());
      rem -= divisor * quo.dat[i];
      while (rem.sign == -1) { rem += divisor; --quo.dat[i];  }
    }
    quo.sign = sign * x.sign; rem.sign = sign;
    quo.trim(); rem.trim();
    return {quo, rem / k};
  }
};
BigInt __gcd(BigInt a, BigInt b) { while (!b.dat.empty()) swap(a %= b, b); return a; }
BigInt __lcm(const BigInt &a, const BigInt &b) { return a / __gcd(a, b) * b; }
BigInt abs(const BigInt &x) { BigInt res = x; res.sign = 1; return res; }
BigInt max(const BigInt &a, const BigInt &b) { return a < b ? b : a; }
BigInt min(const BigInt &a, const BigInt &b) { return a < b ? a : b; }

using rational = Rational<BigInt>;

int main() {
  int n, m, s, t; cin >> n >> m >> s >> t; --s; --t;
  Dinic<int> dinic(n);
  PrimalDual<int, int> pd(n, INF, INF);
  while (m--) {
    int a, b, u, c; cin >> a >> b >> u >> c; --a; --b;
    dinic.add_edge(a, b, u);
    pd.add_edge(a, b, u, c);
  }
  int M = dinic.maximum_flow(s, t, INF);
  rational ans = BigInt(M) * M;
  for (int flow = 0, cost = 0; flow < M;) {
    pd.dijkstra(s);
    assert(pd.dist[t] < INF);
    int nx_flow = M - flow, nx_cost = cost + pd.calc(s, t, nx_flow);
    nx_flow = M - nx_flow;
    int x = nx_flow - flow, y = nx_cost - cost;
    rational f(BigInt(x) * x * M + BigInt(y) * y * flow - BigInt(x) * y * cost, BigInt(x) * x + BigInt(y) * y);
    if (f >= rational(flow) && f <= rational(nx_flow)) {
      rational tmp = (f - rational(flow)) / rational(x) * rational(y) + rational(cost);
      tmp *= tmp;
      chmin(ans, tmp + (-f + rational(M)) * (-f + rational(M)));
    }
    flow = nx_flow; cost = nx_cost;
    chmin(ans, BigInt(cost) * cost + BigInt(M - flow) * (M - flow));
  }
  cout << ans;
  if (ans.den == 1) cout << "/1";
  cout << '\n';
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3476
final_rank: 4

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define NUM 105


struct Data{

	void set(ll arg_denominator,ll arg_numerator){
		denominator = arg_denominator;
		numerator = arg_numerator;
	}
	ll denominator,numerator;
};

struct Dinic{

	//辺を表す構造体(行先、容量、逆辺のインデックス)
	struct Edge{
		Edge(int arg_to,ll arg_capacity,int arg_rev_index){
			to = arg_to;
			capacity = arg_capacity;
			rev_index = arg_rev_index;
		}
		int to,rev_index;
		ll capacity;
	};

	int V;

	vector<Edge> G[NUM];
	ll dist[NUM];
	int cheked_index[NUM];

	void add_edge(int from,int to,ll capacity){
		G[from].push_back(Edge(to,capacity,G[to].size()));
		G[to].push_back(Edge(from,0,G[from].size()-1));
	}

	void bfs(int source){
		for(int i = 0; i < V; i++)dist[i] = -1;
		queue<int> Q;
		dist[source] = 0;
		Q.push(source);

		while(!Q.empty()){
			int node_id = Q.front();
			Q.pop();
			for(int i = 0; i < G[node_id].size(); i++){
				Edge &e = G[node_id][i];
				if(e.capacity > 0 && dist[e.to] < 0){
					dist[e.to] = dist[node_id]+1;
					Q.push(e.to);
				}
			}
		}
	}

	ll dfs(int node_id,int sink,ll flow){
		if(node_id == sink)return flow;

		for(int &i = cheked_index[node_id]; i < G[node_id].size(); i++){
			Edge &e = G[node_id][i];
			if(e.capacity > 0 && dist[node_id] < dist[e.to]){
				ll tmp_flow = dfs(e.to,sink,min(flow,e.capacity));
				if(tmp_flow > 0){
					e.capacity -= tmp_flow;
					G[e.to][e.rev_index].capacity += tmp_flow;
					return tmp_flow;
				}
			}
		}
		return 0;
	}

	ll max_flow(int source,int sink){
		ll flow = 0,add;
		while(true){
			bfs(source);
			if(dist[sink] < 0)break;
			for(int i = 0; i < V; i++)cheked_index[i] = 0;
			while((add = dfs(source,sink,BIG_NUM)) > 0){
				flow += add;
			}
		}
		return flow;
	}
};

struct Info{
	Info(ll arg_flow,ll arg_cost){
		flow = arg_flow;
		cost = arg_cost;
	}
	ll flow,cost;
};

struct Edge{
	Edge(int arg_to,ll arg_capacity,ll arg_cost,int arg_rev_index){
		to = arg_to;
		capacity = arg_capacity;
		cost = arg_cost;
		rev_index = arg_rev_index;
	}

	int to,rev_index;
	ll cost,capacity;
};


int V; //頂点数
vector<Edge> G[NUM]; //グラフの隣接リスト表現
ll dist[NUM]; //最短距離
int pre_node[NUM],pre_edge[NUM]; //直前の頂点と辺
vector<Info> info;

ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}

//分子・分母を約分する
Data reduction(Data A){

	ll common = gcd(A.denominator,A.numerator);

	A.denominator /= common;
	A.numerator /= common;

	return A;
}

//A+B
Data add(Data A,Data B){

	Data ret;

	ll LCM = lcm(A.denominator,B.denominator);

	ll a_mult = LCM/A.denominator;
	ll b_mult = LCM/B.denominator;

	ret.denominator = LCM;

	A.numerator *= a_mult;
	B.numerator *= b_mult;

	ret.numerator = A.numerator+B.numerator;

	return reduction(ret);
}

//A-B
Data subtract(Data A,Data B){

	Data ret;

	ll LCM = lcm(A.denominator,B.denominator);

	ll a_mult = LCM/A.denominator;
	ll b_mult = LCM/B.denominator;

	ret.denominator = LCM;

	A.numerator *= a_mult;
	B.numerator *= b_mult;

	ret.numerator = A.numerator-B.numerator;

	return reduction(ret);
}

//A*B
Data mult(Data A,Data B){

	Data ret;

	ret.numerator = A.numerator*B.numerator;
	ret.denominator = A.denominator*B.denominator;

	return reduction(ret);
}

//A/B
Data divide(Data A,Data B){

	Data ret;

	ret.numerator = A.numerator*B.denominator;
	ret.denominator = A.denominator*B.numerator;

	return reduction(ret);
}

void add_edge(int from,int to,ll capacity,ll cost){
	G[from].push_back(Edge(to,capacity,cost,G[to].size()));
	G[to].push_back(Edge(from,0,-cost,G[from].size()-1));
}

ll min_cost_flow(int source,int sink,ll flow){

	ll max_FLOW = flow;
	ll ret = 0;

	while(flow > 0){
		//ベルマンフォード方により、source-sink間最短経路を求める
		for(int i = 0; i < V; i++)dist[i] = BIG_NUM;
		dist[source] = 0;
		bool update = true;
		while(update){
			update = false;
			for(int node_id = 0; node_id < V; node_id++){
				if(dist[node_id] == BIG_NUM)continue;
				for(int i = 0; i < G[node_id].size(); i++){
					Edge &e = G[node_id][i];
					if(e.capacity > 0 && dist[e.to] > dist[node_id]+e.cost){
						dist[e.to] = dist[node_id]+e.cost; //node_idを経由した方が早い場合
						pre_node[e.to] = node_id;
						pre_edge[e.to] = i;
						update = true;
					}
				}
			}
		}

		if(dist[sink] == BIG_NUM){
			//これ以上流せない
			return -1;
		}

		//source-sink間最短路に沿って目いっぱい流す
		ll tmp_flow = flow;
		for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){
			tmp_flow = min(tmp_flow,G[pre_node[node_id]][pre_edge[node_id]].capacity);
		}
		flow -= tmp_flow;
		ret += tmp_flow*dist[sink];

		for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){
			Edge &e = G[pre_node[node_id]][pre_edge[node_id]];
			e.capacity -= tmp_flow;
			G[node_id][e.rev_index].capacity += tmp_flow;
		}
	}
	return ret;
}

int main(){

	int E;
	Dinic dinic;

	scanf("%d %d",&V,&E);
	dinic.V = V;

	int source,sink;
	scanf("%d %d",&source,&sink);

	source--;
	sink--;

	int from,to;
	ll capacity,cost;

	for(int loop = 0; loop < E; loop++){

		scanf("%d %d %lld %lld",&from,&to,&capacity,&cost);
		from--;
		to--;

		add_edge(from,to,capacity,cost);
		dinic.add_edge(from,to,capacity);
	}

	ll max_FLOW = dinic.max_flow(source,sink); //最大の流量を求める

	info.push_back(Info(0,0));
	ll sum_cost = 0;

	for(int flow = 1; flow <= max_FLOW; flow++){

		cost = min_cost_flow(source,sink,1); //折れ線グラフ作成
		sum_cost += cost;

		info.push_back(Info(flow,sum_cost));
	}

	//最大流量
	Data MAX_FLOW;
	MAX_FLOW.denominator = 1;
	MAX_FLOW.numerator = max_FLOW;

	//微分して0になる箇所がなかった場合のため、仮の答えを求めておく
	ll minimum = HUGE_NUM;

	for(int i = 0; i < info.size(); i++){

		ll tmp = info[i].cost*info[i].cost+(max_FLOW-info[i].flow)*(max_FLOW-info[i].flow);
		minimum = min(minimum,tmp);
	}

	//左端流量からの追加流量で目的関数を微分して、0になる区間があるかどうか調べる
	for(int i = 0; i < info.size()-1; i++){

		//その区間の傾き
		Data slope;
		slope.set(info[i+1].flow-info[i].flow,info[i+1].cost-info[i].cost); //(分母,分子)の順
		slope = reduction(slope);

		/*左端流量-最大流量+区間傾き*左端コスト < 0 < 右端流量-最大流量+区間傾き*右端コストが成り立つか調べる*/

		Data left;
		left.set(1,info[i].flow);

		left = subtract(left,MAX_FLOW);

		Data tmp;
		tmp.set(slope.denominator,slope.numerator*info[i].cost);
		tmp = reduction(tmp);

		left = add(left,tmp);

		if(left.numerator >= 0)continue;

		Data right;
		right.set(1,info[i+1].flow);

		right = subtract(right,MAX_FLOW);

		tmp.set(slope.denominator,slope.numerator*info[i+1].cost);
		tmp = reduction(tmp);

		right = add(right,tmp);

		if(right.numerator <= 0)continue;

		//解あり→追加流量を求める
		Data DENOMINATOR = mult(slope,slope);

		tmp.set(1,1);

		DENOMINATOR = add(DENOMINATOR,tmp);

		Data NUMERATOR;
		NUMERATOR.set(1,max_FLOW-info[i].flow);

		tmp.set(slope.denominator,slope.numerator*info[i].cost);
		tmp = reduction(tmp);

		NUMERATOR = subtract(NUMERATOR,tmp);

		Data delta = divide(NUMERATOR,DENOMINATOR);

		Data L = MAX_FLOW;

		tmp.set(1,info[i].flow);
		tmp = add(tmp,delta);

		L = subtract(L,tmp);
		L = mult(L,L);

		Data R;
		R.set(1,info[i].cost);

		tmp = slope;
		tmp = mult(tmp,delta);

		R = add(R,tmp);
		R = mult(R,R);

		Data ans = add(L,R);

		printf("%lld/%lld\n",ans.numerator,ans.denominator);
		return 0;
	}

	printf("%lld/1\n",minimum);

	return 0;
}
accuracy: 0.9775280898876404
time_ms: 20
memory_kb: 3364
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = __int128;

ll abs(ll a) {
    return a < 0 ? -a : a;
}

template <typename NumType>
class rational {
public:
    rational(NumType n) : num(n), den(1) {}
    rational(NumType n, NumType d) : num(n), den(d) {}

    rational& operator+=(NumType n) {
        num += n * den;
        reduce();
        return *this;
    }
    rational& operator+=(rational const& r) {
        num = num * r.den + r.num * den;
        den = den * r.den;
        reduce();
        return *this;
    }
    rational& operator-=(NumType n) {
        num -= n * den;
        reduce();
        return *this;
    }
    rational& operator-=(rational const& r) {
        num = num * r.den - r.num * den;
        den = den * r.den;
        reduce();
        return *this;
    }
    rational& operator*=(NumType n) {
        num *= n;
        reduce();
        return *this;
    }
    rational& operator*=(rational const& r) {
        num *= r.num;
        den *= r.den;
        reduce();
        return *this;
    }

    void reduce() {
        const ll g = __gcd(abs(num), abs(den));
        num /= g, den /= g;
    }

    NumType numerator() const { return num; }
    NumType denominator() const { return den; }

    bool operator<(rational<NumType> const& r) const {
        return num * r.den < r.num * den;
    }
    bool operator<=(rational<NumType> const& r) const {
        return num * r.den <= r.num * den;
    }

private:
    NumType num, den;
};

template <typename NumType>
rational<NumType> operator+(NumType n, rational<NumType> r) {
    r += n;
    return r;
}
template <typename NumType>
rational<NumType> operator+(rational<NumType> a, rational<NumType> const& b) {
    a += b;
    return a;
}
template <typename NumType>
rational<NumType> operator-(NumType n, rational<NumType> const& r) {
    return rational<NumType>{n, 1} - r;
}
template <typename NumType>
rational<NumType> operator-(rational<NumType> a, rational<NumType> const& b) {
    a -= b;
    return a;
}
template <typename NumType>
rational<NumType> operator*(NumType n, rational<NumType> r) {
    r *= n;
    return r;
}
template <typename NumType>
rational<NumType> operator*(rational<NumType> a, rational<NumType> const& b) {
    a *= b;
    return a;
}

template <typename Edge>
class graph {
    using graph_t = std::vector<std::vector<Edge>>;
public:
    using reference = std::vector<Edge>&;
    using const_reference = std::vector<Edge> const&;
    using iterator = typename graph_t::iterator;
    using const_iterator = typename graph_t::const_iterator;
    using reverse_iterator = typename graph_t::reverse_iterator;

    graph() : g() {}
    graph(int n) : g(n) {}

    reference operator[](int x) { return g[x]; }
    const_reference operator[](int x) const { return g[x]; }

    iterator begin() { return std::begin(g); }
    const_iterator begin() const { return std::begin(g); }
    iterator end() { return std::end(g); }
    const_iterator end() const { return std::end(g); }
    reverse_iterator rbegin() { return std::rbegin(g); }
    reverse_iterator rend() { return std::rend(g); }

    int size() const { return g.size(); }

    void add_node(std::vector<Edge> es) {
        g.push_back(std::move(es));
    }

private:
    std::vector<std::vector<Edge>> g;
};

template <typename Capacity, typename Cost>
struct capacity_weighted_edge {
    using capacity_type = Capacity;
    using cost_type = Cost;
    int to, rev;
    capacity_type cap;
    cost_type cost;
    capacity_weighted_edge(int t, int r, capacity_type cp, cost_type c)
        : to(t), rev(r), cap(cp), cost(c)
    {}
};

template <typename Capacity, typename Cost>
using capacity_weighted_graph = graph<capacity_weighted_edge<Capacity, Cost>>;

template <typename Capacity, typename Cost>
void add_edge(capacity_weighted_graph<Capacity, Cost>& g, int from, int to, Capacity cap, Cost cost) {
    g[from].emplace_back(to, static_cast<int>(g[to].size()), cap, cost);
    g[to].emplace_back(from, static_cast<int>(g[from].size() - 1), Capacity{0}, -cost);
}

template <typename Edge, typename Capacity = typename Edge::capacity_type>
Capacity augment(graph<Edge>& g, std::vector<int> const& level, std::vector<int>& iter, int v, int t, Capacity f) {
    if(v == t) return f;
    for(int& i = iter[v]; i < (int)g[v].size(); ++i) {
        auto& e = g[v][i];
        if(e.cap > 0 && level[v] < level[e.to]) {
            const auto d = augment(g, level, iter, e.to, t, std::min(f, e.cap));
            if(d > 0) {
                e.cap -= d;
                g[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

template <typename Edge, typename Capacity = typename Edge::capacity_type>
Capacity max_flow(graph<Edge>& g, int s, int t) {
    const auto inf = std::numeric_limits<Capacity>::max() / 2;
    Capacity flow = 0;
    while(true) {
        std::vector<int> level(g.size(), -1);
        level[s] = 0;
        std::queue<int> que;
        que.push(s);
        while(!que.empty()) {
            const int v = que.front();
            que.pop();
            for(auto const& e : g[v]) {
                if(e.cap > 0 && level[e.to] < 0) {
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }

        if(level[t] < 0) return flow;
        std::vector<int> iter(g.size());
        Capacity f{0};
        while((f = augment(g, level, iter, s, t, inf)) > 0) {
            flow += f;
        }
    }
}

template <typename Edge>
typename Edge::cost_type min_cost_flow(graph<Edge>& g, int s, int t, typename Edge::capacity_type f) {
    using cost_type = typename Edge::cost_type;
    using P = std::pair<cost_type, int>;
    const auto inf = std::numeric_limits<cost_type>::max() / 2;
    cost_type res = 0;
    std::vector<cost_type> h(g.size()), dist(g.size());
    std::vector<int> prevv(g.size()), preve(g.size());
    while(f > 0) {
        std::priority_queue<P, std::vector<P>, std::greater<>> que;
        std::fill(std::begin(dist), std::end(dist), inf);
        dist[s] = 0;
        que.emplace(dist[s], s);
        while(!que.empty()) {
            const auto cur_d = que.top().first;
            const int v = que.top().second;
            que.pop();
            if(dist[v] < cur_d) continue;
            for(int i = 0; i < (int)g[v].size(); ++i) {
                auto& e = g[v][i];
                if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                    dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    que.emplace(dist[e.to], e.to);
                }
            }
        }
        if(dist[t] == inf) return -1;
        for(int v = 0; v < (int)g.size(); ++v) {
            h[v] += dist[v];
        }

        auto d = f;
        for(int v = t; v != s; v = prevv[v]) {
            d = std::min(d, g[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d * h[t];
        for(int v = t; v != s; v = prevv[v]) {
            auto& e = g[prevv[v]][preve[v]];
            e.cap -= d;
            g[v][e.rev].cap += d;
        }
    }
    return res;
}

int main() {
    int n, m; cin >> n >> m;
    capacity_weighted_graph<int, int> g(n);
    int s, t; cin >> s >> t;
    s--, t--;
    for(int i = 0; i < m; ++i) {
        int a, b, u, c; cin >> a >> b >> u >> c;
        add_edge(g, a - 1, b - 1, u, c);
    }

    const ll M = [&] { auto tmp = g; return max_flow(tmp, s, t); }();

    rational<ll> ans{M * M, 1};
    auto calc_cost = [&] (ll fi, ll ci, ll ci_sum, rational<ll> delta) {
        const auto a = M - (fi + delta), b = ci_sum + ci * delta;
        return a * a + b * b;
    };
    ll ci_sum = 0;
    for(int i = 0; i < M; ++i) {
        const ll ci = min_cost_flow(g, s, t, 1);
        if(0 <= M - i - ci * ci_sum && M - i - ci * ci_sum <= ci * ci + 1) {
            auto delta = rational<ll>{M - i - ci * ci_sum, ci * ci + 1};
            delta.reduce();
            ans = min(ans, calc_cost(i, ci, ci_sum, delta));
        }
        ci_sum += ci;
        ans = min(ans, calc_cost(i + 1, 0, ci_sum, rational<ll>{0, 1}));
    }

    cout << (long long)ans.numerator() << "/" << (long long)ans.denominator() << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 3212
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

template <typename NumType>
class rational {
public:
    rational(NumType n) : num(n), den(1) {}
    rational(NumType n, NumType d) : num(n), den(d) {}

    rational& operator+=(NumType n) {
        num += n * den;
        reduce();
        return *this;
    }
    rational& operator+=(rational const& r) {
        const ll g = __gcd(r.den, den);
        num = num * (r.den / g) + r.num * (den / g);
        den = den / g * r.den;
        reduce();
        return *this;
    }
    rational& operator-=(NumType n) {
        num -= n * den;
        reduce();
        return *this;
    }
    rational& operator-=(rational const& r) {
        const ll g = __gcd(r.den, den);
        num = num * (r.den / g) - r.num * (den / g);
        den = den / g * r.den;
        reduce();
        return *this;
    }
    rational& operator*=(NumType n) {
        num *= n;
        reduce();
        return *this;
    }
    rational& operator*=(rational const& r) {
        num *= r.num;
        den *= r.den;
        reduce();
        return *this;
    }

    void reduce() {
        const ll g = __gcd(abs(num), abs(den));
        num /= g, den /= g;
    }

    NumType numerator() const { return num; }
    NumType denominator() const { return den; }

    bool operator<(rational<NumType> const& r) const {
        const ll g = __gcd(den, r.den);
        return num * (r.den / g) < r.num * (den / g);
    }
    bool operator<=(rational<NumType> const& r) const {
        const ll g = __gcd(den, r.den);
        return num * (r.den / g) <= r.num * (den / g);
    }

private:
    NumType num, den;
};

template <typename NumType>
rational<NumType> operator+(NumType n, rational<NumType> r) {
    r += n;
    return r;
}
template <typename NumType>
rational<NumType> operator+(rational<NumType> a, rational<NumType> const& b) {
    a += b;
    return a;
}
template <typename NumType>
rational<NumType> operator-(NumType n, rational<NumType> const& r) {
    return rational<NumType>{n, 1} - r;
}
template <typename NumType>
rational<NumType> operator-(rational<NumType> a, rational<NumType> const& b) {
    a -= b;
    return a;
}
template <typename NumType>
rational<NumType> operator*(NumType n, rational<NumType> r) {
    r *= n;
    return r;
}
template <typename NumType>
rational<NumType> operator*(rational<NumType> a, rational<NumType> const& b) {
    a *= b;
    return a;
}

template <typename Edge>
class graph {
    using graph_t = std::vector<std::vector<Edge>>;
public:
    using reference = std::vector<Edge>&;
    using const_reference = std::vector<Edge> const&;
    using iterator = typename graph_t::iterator;
    using const_iterator = typename graph_t::const_iterator;
    using reverse_iterator = typename graph_t::reverse_iterator;

    graph() : g() {}
    graph(int n) : g(n) {}

    reference operator[](int x) { return g[x]; }
    const_reference operator[](int x) const { return g[x]; }

    iterator begin() { return std::begin(g); }
    const_iterator begin() const { return std::begin(g); }
    iterator end() { return std::end(g); }
    const_iterator end() const { return std::end(g); }
    reverse_iterator rbegin() { return std::rbegin(g); }
    reverse_iterator rend() { return std::rend(g); }

    int size() const { return g.size(); }

    void add_node(std::vector<Edge> es) {
        g.push_back(std::move(es));
    }

private:
    std::vector<std::vector<Edge>> g;
};

template <typename Capacity, typename Cost>
struct capacity_weighted_edge {
    using capacity_type = Capacity;
    using cost_type = Cost;
    int to, rev;
    capacity_type cap;
    cost_type cost;
    capacity_weighted_edge(int t, int r, capacity_type cp, cost_type c)
        : to(t), rev(r), cap(cp), cost(c)
    {}
};

template <typename Capacity, typename Cost>
using capacity_weighted_graph = graph<capacity_weighted_edge<Capacity, Cost>>;

template <typename Capacity, typename Cost>
void add_edge(capacity_weighted_graph<Capacity, Cost>& g, int from, int to, Capacity cap, Cost cost) {
    g[from].emplace_back(to, static_cast<int>(g[to].size()), cap, cost);
    g[to].emplace_back(from, static_cast<int>(g[from].size() - 1), Capacity{0}, -cost);
}

template <typename Edge, typename Capacity = typename Edge::capacity_type>
Capacity augment(graph<Edge>& g, std::vector<int> const& level, std::vector<int>& iter, int v, int t, Capacity f) {
    if(v == t) return f;
    for(int& i = iter[v]; i < (int)g[v].size(); ++i) {
        auto& e = g[v][i];
        if(e.cap > 0 && level[v] < level[e.to]) {
            const auto d = augment(g, level, iter, e.to, t, std::min(f, e.cap));
            if(d > 0) {
                e.cap -= d;
                g[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

template <typename Edge, typename Capacity = typename Edge::capacity_type>
Capacity max_flow(graph<Edge>& g, int s, int t) {
    const auto inf = std::numeric_limits<Capacity>::max() / 2;
    Capacity flow = 0;
    while(true) {
        std::vector<int> level(g.size(), -1);
        level[s] = 0;
        std::queue<int> que;
        que.push(s);
        while(!que.empty()) {
            const int v = que.front();
            que.pop();
            for(auto const& e : g[v]) {
                if(e.cap > 0 && level[e.to] < 0) {
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }

        if(level[t] < 0) return flow;
        std::vector<int> iter(g.size());
        Capacity f{0};
        while((f = augment(g, level, iter, s, t, inf)) > 0) {
            flow += f;
        }
    }
}

template <typename Edge>
typename Edge::cost_type min_cost_flow(graph<Edge>& g, int s, int t, typename Edge::capacity_type f) {
    using cost_type = typename Edge::cost_type;
    using P = std::pair<cost_type, int>;
    const auto inf = std::numeric_limits<cost_type>::max() / 2;
    cost_type res = 0;
    std::vector<cost_type> h(g.size()), dist(g.size());
    std::vector<int> prevv(g.size()), preve(g.size());
    while(f > 0) {
        std::priority_queue<P, std::vector<P>, std::greater<>> que;
        std::fill(std::begin(dist), std::end(dist), inf);
        dist[s] = 0;
        que.emplace(dist[s], s);
        while(!que.empty()) {
            const auto cur_d = que.top().first;
            const int v = que.top().second;
            que.pop();
            if(dist[v] < cur_d) continue;
            for(int i = 0; i < (int)g[v].size(); ++i) {
                auto& e = g[v][i];
                if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                    dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    que.emplace(dist[e.to], e.to);
                }
            }
        }
        if(dist[t] == inf) return -1;
        for(int v = 0; v < (int)g.size(); ++v) {
            h[v] += dist[v];
        }

        auto d = f;
        for(int v = t; v != s; v = prevv[v]) {
            d = std::min(d, g[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d * h[t];
        for(int v = t; v != s; v = prevv[v]) {
            auto& e = g[prevv[v]][preve[v]];
            e.cap -= d;
            g[v][e.rev].cap += d;
        }
    }
    return res;
}

int main() {
    int n, m; cin >> n >> m;
    capacity_weighted_graph<int, int> g(n);
    int s, t; cin >> s >> t;
    s--, t--;
    for(int i = 0; i < m; ++i) {
        int a, b, u, c; cin >> a >> b >> u >> c;
        add_edge(g, a - 1, b - 1, u, c);
    }

    const ll M = [&] { auto tmp = g; return max_flow(tmp, s, t); }();

    rational<ll> ans{M * M, 1};
    auto calc_cost = [&] (ll fi, ll ci, ll ci_sum, rational<ll> delta) {
        const auto a = M - (fi + delta), b = ci_sum + ci * delta;
        return a * a + b * b;
    };
    ll ci_sum = 0;
    for(int i = 0; i < M; ++i) {
        const ll ci = min_cost_flow(g, s, t, 1);
        if(0 <= M - i - ci * ci_sum && M - i - ci * ci_sum <= ci * ci + 1) {
            auto delta = rational<ll>{M - i - ci * ci_sum, ci * ci + 1};
            delta.reduce();
            ans = min(ans, calc_cost(i, ci, ci_sum, delta));
        }
        ci_sum += ci;
        ans = min(ans, calc_cost(i + 1, 0, ci_sum, rational<ll>{0, 1}));
    }

    cout << ans.numerator() << "/" << ans.denominator() << endl;
}
accuracy: 0.9775280898876404
time_ms: 30
memory_kb: 3212
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

template <typename NumType>
class rational {
public:
    rational(NumType n) : num(n), den(1) {}
    rational(NumType n, NumType d) : num(n), den(d) {}

    rational& operator+=(NumType n) {
        num += n * den;
        reduce();
        return *this;
    }
    rational& operator+=(rational const& r) {
        num = num * r.den + r.num * den;
        den *= r.den;
        reduce();
        return *this;
    }
    rational& operator-=(NumType n) {
        num -= n * den;
        reduce();
        return *this;
    }
    rational& operator-=(rational const& r) {
        num = num * r.den - r.num * den;
        den *= r.den;
        reduce();
        return *this;
    }
    rational& operator*=(NumType n) {
        num *= n;
        reduce();
        return *this;
    }
    rational& operator*=(rational const& r) {
        num *= r.num;
        den *= r.den;
        reduce();
        return *this;
    }

    void reduce() {
        const ll g = __gcd(abs(num), abs(den));
        num /= g, den /= g;
    }

    NumType numerator() const { return num; }
    NumType denominator() const { return den; }

    bool operator<(rational<NumType> const& r) const {
        return num * r.den < r.num * den;
    }
    bool operator<=(rational<NumType> const& r) const {
        return num * r.den < r.num * den;
    }

private:
    NumType num, den;
};

template <typename NumType>
rational<NumType> operator+(NumType n, rational<NumType> r) {
    r += n;
    return r;
}
template <typename NumType>
rational<NumType> operator+(rational<NumType> a, rational<NumType> const& b) {
    a += b;
    return a;
}
template <typename NumType>
rational<NumType> operator-(NumType n, rational<NumType> const& r) {
    return rational<NumType>{n, 1} - r;
}
template <typename NumType>
rational<NumType> operator-(rational<NumType> a, rational<NumType> const& b) {
    a -= b;
    return a;
}
template <typename NumType>
rational<NumType> operator*(NumType n, rational<NumType> r) {
    r *= n;
    return r;
}
template <typename NumType>
rational<NumType> operator*(rational<NumType> a, rational<NumType> const& b) {
    a *= b;
    return a;
}

template <typename Edge>
class graph {
    using graph_t = std::vector<std::vector<Edge>>;
public:
    using reference = std::vector<Edge>&;
    using const_reference = std::vector<Edge> const&;
    using iterator = typename graph_t::iterator;
    using const_iterator = typename graph_t::const_iterator;
    using reverse_iterator = typename graph_t::reverse_iterator;

    graph() : g() {}
    graph(int n) : g(n) {}

    reference operator[](int x) { return g[x]; }
    const_reference operator[](int x) const { return g[x]; }

    iterator begin() { return std::begin(g); }
    const_iterator begin() const { return std::begin(g); }
    iterator end() { return std::end(g); }
    const_iterator end() const { return std::end(g); }
    reverse_iterator rbegin() { return std::rbegin(g); }
    reverse_iterator rend() { return std::rend(g); }

    int size() const { return g.size(); }

    void add_node(std::vector<Edge> es) {
        g.push_back(std::move(es));
    }

private:
    std::vector<std::vector<Edge>> g;
};

template <typename Capacity, typename Cost>
struct capacity_weighted_edge {
    using capacity_type = Capacity;
    using cost_type = Cost;
    int to, rev;
    capacity_type cap;
    cost_type cost;
    capacity_weighted_edge(int t, int r, capacity_type cp, cost_type c)
        : to(t), rev(r), cap(cp), cost(c)
    {}
};

template <typename Capacity, typename Cost>
using capacity_weighted_graph = graph<capacity_weighted_edge<Capacity, Cost>>;

template <typename Capacity, typename Cost>
void add_edge(capacity_weighted_graph<Capacity, Cost>& g, int from, int to, Capacity cap, Cost cost) {
    g[from].emplace_back(to, static_cast<int>(g[to].size()), cap, cost);
    g[to].emplace_back(from, static_cast<int>(g[from].size() - 1), Capacity{0}, -cost);
}

template <typename Edge, typename Capacity = typename Edge::capacity_type>
Capacity augment(graph<Edge>& g, std::vector<int> const& level, std::vector<int>& iter, int v, int t, Capacity f) {
    if(v == t) return f;
    for(int& i = iter[v]; i < (int)g[v].size(); ++i) {
        auto& e = g[v][i];
        if(e.cap > 0 && level[v] < level[e.to]) {
            const auto d = augment(g, level, iter, e.to, t, std::min(f, e.cap));
            if(d > 0) {
                e.cap -= d;
                g[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

template <typename Edge, typename Capacity = typename Edge::capacity_type>
Capacity max_flow(graph<Edge>& g, int s, int t) {
    const auto inf = std::numeric_limits<Capacity>::max() / 2;
    Capacity flow = 0;
    while(true) {
        std::vector<int> level(g.size(), -1);
        level[s] = 0;
        std::queue<int> que;
        que.push(s);
        while(!que.empty()) {
            const int v = que.front();
            que.pop();
            for(auto const& e : g[v]) {
                if(e.cap > 0 && level[e.to] < 0) {
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }

        if(level[t] < 0) return flow;
        std::vector<int> iter(g.size());
        Capacity f{0};
        while((f = augment(g, level, iter, s, t, inf)) > 0) {
            flow += f;
        }
    }
}

template <typename Edge>
typename Edge::cost_type min_cost_flow(graph<Edge>& g, int s, int t, typename Edge::capacity_type f) {
    using cost_type = typename Edge::cost_type;
    using P = std::pair<cost_type, int>;
    const auto inf = std::numeric_limits<cost_type>::max() / 2;
    cost_type res = 0;
    std::vector<cost_type> h(g.size()), dist(g.size());
    std::vector<int> prevv(g.size()), preve(g.size());
    while(f > 0) {
        std::priority_queue<P, std::vector<P>, std::greater<>> que;
        std::fill(std::begin(dist), std::end(dist), inf);
        dist[s] = 0;
        que.emplace(dist[s], s);
        while(!que.empty()) {
            const auto cur_d = que.top().first;
            const int v = que.top().second;
            que.pop();
            if(dist[v] < cur_d) continue;
            for(int i = 0; i < (int)g[v].size(); ++i) {
                auto& e = g[v][i];
                if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                    dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    que.emplace(dist[e.to], e.to);
                }
            }
        }
        if(dist[t] == inf) return -1;
        for(int v = 0; v < (int)g.size(); ++v) {
            h[v] += dist[v];
        }

        auto d = f;
        for(int v = t; v != s; v = prevv[v]) {
            d = std::min(d, g[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d * h[t];
        for(int v = t; v != s; v = prevv[v]) {
            auto& e = g[prevv[v]][preve[v]];
            e.cap -= d;
            g[v][e.rev].cap += d;
        }
    }
    return res;
}

int main() {
    int n, m; cin >> n >> m;
    capacity_weighted_graph<int, int> g(n);
    int s, t; cin >> s >> t;
    s--, t--;
    for(int i = 0; i < m; ++i) {
        int a, b, u, c; cin >> a >> b >> u >> c;
        add_edge(g, a - 1, b - 1, u, c);
    }

    const ll M = [&] { auto tmp = g; return max_flow(tmp, s, t); }();

    rational<ll> ans{M * M, 1};
    auto calc_cost = [&] (ll fi, ll ci, ll ci_sum, rational<ll> delta) {
        const auto a = M - (fi + delta), b = ci_sum + ci * delta;
        return a * a + b * b;
    };
    ll ci_sum = 0;
    for(int i = 0; i < M; ++i) {
        const ll ci = min_cost_flow(g, s, t, 1);
        if(0 <= M - i - ci * ci_sum && M - i - ci * ci_sum <= ci * ci + 1) {
            auto delta = rational<ll>{M - i - ci * ci_sum, ci * ci + 1};
            delta.reduce();
            ans = min(ans, calc_cost(i, ci, ci_sum, delta));
        }
        ci_sum += ci;
        ans = min(ans, calc_cost(i + 1, 0, ci_sum, rational<ll>{0, 1}));
    }

    cout << ans.numerator() << "/" << ans.denominator() << endl;
}
accuracy: 0.9662921348314607
time_ms: 30
memory_kb: 3216
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt __builtin_popcountll

#define INF INT_MAX/3
#define MAX_V 300

struct edge{
  int to,cap,cost,rev;
};

int V;
vector<edge> g[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];

void init(int v){
  V=v;
  for(int i=0;i<MAX_V;i++){
    g[i].clear();
  }
}

void add_edge(int from,int to,int cap,int cost){
  g[from].push_back((edge){to,cap,cost,(int)g[to].size()});
  g[to].push_back((edge){from,0,-cost,(int)g[from].size()-1});
}

int min_cost_flow(int s,int t,int f){
  int res=0;
  memset(h,0,sizeof(h));
  while(f>0){
    fill(dist,dist+V,INF);
    dist[s]=0;
    bool update=true;
    while(update){
      update=false;
      for(int v=0;v<V;v++){
        if(dist[v]==INF)continue;
        for(int i=0;i<(int)g[v].size();i++){
          edge &e=g[v][i];
          if(e.cap>0&&dist[e.to]>dist[v]+e.cost){
            dist[e.to]=dist[v]+e.cost;
            prevv[e.to]=v;
            preve[e.to]=i;
            update=true;
          }
        }
      }
    }
    if(dist[t]==INF) return INF;

    int d=f;
    for(int v=t;v!=s;v=prevv[v]){
      d=min(d,g[prevv[v]][preve[v]].cap);
    }
    f-=d;
    res+=d*dist[t];
    for(int v=t;v!=s;v=prevv[v]){
      edge &e=g[prevv[v]][preve[v]];
      e.cap-=d;
      g[v][e.rev].cap+=d;
    }
  }
  return res;
}

bool cmp(__int128 p1,__int128 q1,__int128 p2,__int128 q2){ // p1/q1 <= p2/q2
  return p1*q2 <= p2*q1;
}

int N,M,s,t;
vector<ll> cs;

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin>>N>>M>>s>>t;
  s--;t--;
  init(N);
  rep(i,M){
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    a--;b--;
    add_edge(a,b,c,d);
  }

  ll maxf=0,crtc=0;
  cs.push_back(0);
  while(1){
    int tmp=min_cost_flow(s,t,1);
    if(tmp==INF)break;
    crtc+=tmp;
    cs.push_back(crtc);
    maxf++;
  }

  P resc=P(maxf*maxf,1);

  rep(i,maxf){
    __int128 fl=i,fr=i+1;
    __int128 cl=cs[i],cr=cs[i+1];
    __int128 d=cr-cl;
    __int128 rp=maxf+d*d*fl-d*cl,rq=d*d+1;
    if(cmp(fl,1,rp,rq)&&cmp(rp,rq,fr,1)){
      __int128 bp=(d*(rp-rq*fl)+rq*cl)*(d*(rp-rq*fl)+rq*cl)+(rq*maxf-rp)*(rq*maxf-rp),bq=rq*rq;
      if(cmp(bp,bq,resc.fi,resc.se)){
        __int128 gc=__gcd(bp,bq);
        resc=P(bp/gc,bq/gc);
      }
    }else{
      __int128 bl=cl*cl+(maxf-fl)*(maxf-fl);
      __int128 br=cr*cr+(maxf-fr)*(maxf-fr);
      if(bl<=br){
        if(cmp(bl,1,resc.fi,resc.se)){
          resc=P((ll)bl,1);
        }
      }else{
        if(cmp(br,1,resc.fi,resc.se)){
          resc=P((ll)br,1);
        }
      }
    }
  }

  cout<<resc.fi<<"/"<<resc.se<<endl;

  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3268
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt __builtin_popcountll

#define INF INT_MAX/3
#define MAX_V 300

struct edge{
  int to,cap,cost,rev;
};

int V;
vector<edge> g[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];

void init(int v){
  V=v;
  for(int i=0;i<MAX_V;i++){
    g[i].clear();
  }
}

void add_edge(int from,int to,int cap,int cost){
  g[from].push_back((edge){to,cap,cost,(int)g[to].size()});
  g[to].push_back((edge){from,0,-cost,(int)g[from].size()-1});
}

int min_cost_flow(int s,int t,int f){
  int res=0;
  memset(h,0,sizeof(h));
  while(f>0){
    fill(dist,dist+V,INF);
    dist[s]=0;
    bool update=true;
    while(update){
      update=false;
      for(int v=0;v<V;v++){
        if(dist[v]==INF)continue;
        for(int i=0;i<(int)g[v].size();i++){
          edge &e=g[v][i];
          if(e.cap>0&&dist[e.to]>dist[v]+e.cost){
            dist[e.to]=dist[v]+e.cost;
            prevv[e.to]=v;
            preve[e.to]=i;
            update=true;
          }
        }
      }
    }
    if(dist[t]==INF) return INF;

    int d=f;
    for(int v=t;v!=s;v=prevv[v]){
      d=min(d,g[prevv[v]][preve[v]].cap);
    }
    f-=d;
    res+=d*dist[t];
    for(int v=t;v!=s;v=prevv[v]){
      edge &e=g[prevv[v]][preve[v]];
      e.cap-=d;
      g[v][e.rev].cap+=d;
    }
  }
  return res;
}

bool cmp(ll p1,ll q1,ll p2,ll q2){ // p1/q1 <= p2/q2
  return p1*q2 <= p2*q1;
}

P modify(P p){
  ll gc=__gcd(p.fi,p.se);
  return P(p.fi/gc,p.se/gc);
}

int N,M,s,t;
vector<ll> cs;

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin>>N>>M>>s>>t;
  s--;t--;
  init(N);
  rep(i,M){
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    a--;b--;
    add_edge(a,b,c,d);
  }

  ll maxf=0,crtc=0;
  cs.push_back(0);
  while(1){
    int tmp=min_cost_flow(s,t,1);
    if(tmp==INF)break;
    crtc+=tmp;
    cs.push_back(crtc);
    maxf++;
  }

  P resc=P(maxf*maxf,1);
  rep(i,maxf){
    ll fl=i,fr=i+1;
    ll cl=cs[i],cr=cs[i+1];
    ll d=cr-cl;
    ll rp=maxf+d*d*fl-d*cl,rq=d*d+1;
    if(cmp(fl,1,rp,rq)&&cmp(rp,rq,fr,1)){
      ll bp=(d*(rp-rq*fl)+rq*cl)*(d*(rp-rq*fl)+rq*cl)+(rq*maxf-rp)*(rq*maxf-rp),bq=rq*rq;
      if(cmp(bp,bq,resc.fi,resc.se)){
        resc=P(bp,bq); resc=modify(resc);
      }
    }else{
      ll bl=cl*cl+(maxf-fl)*(maxf-fl);
      ll br=cr*cr+(maxf-fr)*(maxf-fr);
      if(bl<=br){
        if(cmp(bl,1,resc.fi,resc.se)){
          resc=P(bl,1); resc=modify(resc);
        }
      }else{
        if(cmp(br,1,resc.fi,resc.se)){
          resc=P(br,1); resc=modify(resc);
        }
      }
    }
  }

  resc=modify(resc);
  cout<<resc.fi<<"/"<<resc.se<<endl;

  return 0;
}
accuracy: 0.9775280898876404
time_ms: 20
memory_kb: 3268
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt __builtin_popcountll

#define INF INT_MAX/3
#define MAX_V 300

struct edge{
  int to,cap,cost,rev;
};

int V;
vector<edge> g[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];

void init(int v){
  V=v;
  for(int i=0;i<MAX_V;i++){
    g[i].clear();
  }
}

void add_edge(int from,int to,int cap,int cost){
  g[from].push_back((edge){to,cap,cost,(int)g[to].size()});
  g[to].push_back((edge){from,0,-cost,(int)g[from].size()-1});
}

int min_cost_flow(int s,int t,int f){
  int res=0;
  memset(h,0,sizeof(h));
  while(f>0){
    fill(dist,dist+V,INF);
    dist[s]=0;
    bool update=true;
    while(update){
      update=false;
      for(int v=0;v<V;v++){
        if(dist[v]==INF)continue;
        for(int i=0;i<(int)g[v].size();i++){
          edge &e=g[v][i];
          if(e.cap>0&&dist[e.to]>dist[v]+e.cost){
            dist[e.to]=dist[v]+e.cost;
            prevv[e.to]=v;
            preve[e.to]=i;
            update=true;
          }
        }
      }
    }
    if(dist[t]==INF) return INF;

    int d=f;
    for(int v=t;v!=s;v=prevv[v]){
      d=min(d,g[prevv[v]][preve[v]].cap);
    }
    f-=d;
    res+=d*dist[t];
    for(int v=t;v!=s;v=prevv[v]){
      edge &e=g[prevv[v]][preve[v]];
      e.cap-=d;
      g[v][e.rev].cap+=d;
    }
  }
  return res;
}

bool cmp(ll p1,ll q1,ll p2,ll q2){ // p1/q1 <= p2/q2
  return p1*q2 <= p2*q1;
}

int N,M,s,t;
vector<ll> cs;

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin>>N>>M>>s>>t;
  s--;t--;
  init(N);
  rep(i,M){
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    a--;b--;
    add_edge(a,b,c,d);
  }

  ll maxf=0,crtc=0;
  cs.push_back(0);
  while(1){
    int tmp=min_cost_flow(s,t,1);
    if(tmp==INF)break;
    crtc+=tmp;
    cs.push_back(crtc);
    maxf++;
  }

  P resc=P(maxf*maxf,1);
  rep(i,maxf){
    ll fl=i,fr=i+1;
    ll cl=cs[i],cr=cs[i+1];
    ll d=cr-cl;
    ll rp=maxf+d*d*fl-d*cl,rq=d*d+1;
    if(cmp(fl,1,rp,rq)&&cmp(rp,rq,fr,1)){
      ll bp=(d*(rp-rq*fl)+rq*cl)*(d*(rp-rq*fl)+rq*cl)+(rq*maxf-rp)*(rq*maxf-rp),bq=rq*rq;
      if(cmp(bp,bq,resc.fi,resc.se)){
        resc=P(bp,bq);
      }
    }else{
      ll bl=cl*cl+(maxf-fl)*(maxf-fl);
      ll br=cr*cr+(maxf-fr)*(maxf-fr);
      if(bl<=br){
        if(cmp(bl,1,resc.fi,resc.se)){
          resc=P(bl,1);
        }
      }else{
        if(cmp(br,1,resc.fi,resc.se)){
          resc=P(br,1);
        }
      }
    }
  }

  ll gc=__gcd(resc.fi,resc.se);
  cout<<resc.fi/gc<<"/"<<resc.se/gc<<endl;

  return 0;
}
accuracy: 0.9662921348314607
time_ms: 10
memory_kb: 3268
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt __builtin_popcountll

#define INF INT_MAX/3
#define MAX_V 300

struct edge{
  int to,cap,cost,rev;
};

int V;
vector<edge> g[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];

void init(int v){
  V=v;
  for(int i=0;i<MAX_V;i++){
    g[i].clear();
  }
}

void add_edge(int from,int to,int cap,int cost){
  g[from].push_back((edge){to,cap,cost,(int)g[to].size()});
  g[to].push_back((edge){from,0,-cost,(int)g[from].size()-1});
}

int min_cost_flow(int s,int t,int f){
  int res=0;
  memset(h,0,sizeof(h));
  while(f>0){
    fill(dist,dist+V,INF);
    dist[s]=0;
    bool update=true;
    while(update){
      update=false;
      for(int v=0;v<V;v++){
        if(dist[v]==INF)continue;
        for(int i=0;i<(int)g[v].size();i++){
          edge &e=g[v][i];
          if(e.cap>0&&dist[e.to]>dist[v]+e.cost){
            dist[e.to]=dist[v]+e.cost;
            prevv[e.to]=v;
            preve[e.to]=i;
            update=true;
          }
        }
      }
    }
    if(dist[t]==INF) return INF;

    int d=f;
    for(int v=t;v!=s;v=prevv[v]){
      d=min(d,g[prevv[v]][preve[v]].cap);
    }
    f-=d;
    res+=d*dist[t];
    for(int v=t;v!=s;v=prevv[v]){
      edge &e=g[prevv[v]][preve[v]];
      e.cap-=d;
      g[v][e.rev].cap+=d;
    }
  }
  return res;
}

bool cmp(ll p1,ll q1,ll p2,ll q2){ // p1/q1 <= p2/q2
  return p1*q2 <= p2*q1;
}

int N,M,s,t;
vector<ll> cs;

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin>>N>>M>>s>>t;
  s--;t--;
  init(N);
  rep(i,M){
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    a--;b--;
    add_edge(a,b,c,d);
  }

  ll maxf=0,crtc=0;
  cs.push_back(0);
  while(1){
    int tmp=min_cost_flow(s,t,1);
    if(tmp==INF)break;
    crtc+=tmp;
    cs.push_back(crtc);
    maxf++;
  }

  P resc=P(1e8,1);
  rep(i,maxf){
    ll fl=i,fr=i+1;
    ll cl=cs[i],cr=cs[i+1];
    ll d=cr-cl;
    ll rp=maxf+d*d*fl-d*cl,rq=d*d+1;
    if(cmp(fl,1,rp,rq)&&cmp(rp,rq,fr,1)){
      ll bp=(d*(rp-rq*fl)+rq*cl)*(d*(rp-rq*fl)+rq*cl)+(rq*maxf-rp)*(rq*maxf-rp),bq=rq*rq;
      if(cmp(bp,bq,resc.fi,resc.se)){
        resc=P(bp,bq);
      }
    }else{
      ll bl=cl*cl+(maxf-fl)*(maxf-fl);
      ll br=cr*cr+(maxf-fr)*(maxf-fr);
      if(bl<=br){
        if(cmp(bl,1,resc.fi,resc.se)){
          resc=P(bl,1);
        }
      }else{
        if(cmp(br,1,resc.fi,resc.se)){
          resc=P(br,1);
        }
      }
    }
  }

  ll gc=__gcd(resc.fi,resc.se);
  cout<<resc.fi/gc<<"/"<<resc.se/gc<<endl;

  return 0;
}
accuracy: 0.9325842696629213
time_ms: 10
memory_kb: 3264
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt __builtin_popcountll

#define INF INT_MAX/3
#define MAX_V 300

struct edge{
  int to,cap,cost,rev;
};

int V;
vector<edge> g[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];

void init(int v){
  V=v;
  for(int i=0;i<MAX_V;i++){
    g[i].clear();
  }
}

void add_edge(int from,int to,int cap,int cost){
  g[from].push_back((edge){to,cap,cost,(int)g[to].size()});
  g[to].push_back((edge){from,0,-cost,(int)g[from].size()-1});
}

int min_cost_flow(int s,int t,int f){
  int res=0;
  memset(h,0,sizeof(h));
  while(f>0){
    fill(dist,dist+V,INF);
    dist[s]=0;
    bool update=true;
    while(update){
      update=false;
      for(int v=0;v<V;v++){
        if(dist[v]==INF)continue;
        for(int i=0;i<(int)g[v].size();i++){
          edge &e=g[v][i];
          if(e.cap>0&&dist[e.to]>dist[v]+e.cost){
            dist[e.to]=dist[v]+e.cost;
            prevv[e.to]=v;
            preve[e.to]=i;
            update=true;
          }
        }
      }
    }
    if(dist[t]==INF) return INF;

    int d=f;
    for(int v=t;v!=s;v=prevv[v]){
      d=min(d,g[prevv[v]][preve[v]].cap);
    }
    f-=d;
    res+=d*dist[t];
    for(int v=t;v!=s;v=prevv[v]){
      edge &e=g[prevv[v]][preve[v]];
      e.cap-=d;
      g[v][e.rev].cap+=d;
    }
  }
  return res;
}

bool cmp(ll p1,ll q1,ll p2,ll q2){ // p1/q1 <= p2/q2
  return p1*q2 <= p2*q1;
}

int N,M,s,t;
vector<ll> cs;

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin>>N>>M>>s>>t;
  s--;t--;
  init(N);
  rep(i,M){
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    a--;b--;
    add_edge(a,b,c,d);
  }

  ll maxf=0,crtc=0;
  cs.push_back(0);
  while(1){
    int tmp=min_cost_flow(s,t,1);
    if(tmp==INF)break;
    crtc+=tmp;
    cs.push_back(crtc);
    maxf++;
  }

  P resc=P(9e10,1);
  rep(i,maxf){
    ll fl=i,fr=i+1;
    ll cl=cs[i],cr=cs[i+1];
    ll d=cr-cl;
    ll rp=maxf+d*d*fl-d*cl,rq=d*d+1;
    if(cmp(fl,1,rp,rq)&&cmp(rp,rq,fr,1)){
      ll bp=(d*(rp-rq*fl)+rq*cl)*(d*(rp-rq*fl)+rq*cl)+(rq*maxf-rp)*(rq*maxf-rp),bq=rq*rq;
      if(cmp(bp,bq,resc.fi,resc.se)){
        resc=P(bp,bq);
      }
    }else{
      ll bl=cl*cl+(maxf-fl)*(maxf-fl);
      ll br=cr*cr+(maxf-fr)*(maxf-fr);
      if(bl<=br){
        if(cmp(bl,1,resc.fi,resc.se)){
          resc=P(bl,1);
        }
      }else{
        if(cmp(br,1,resc.fi,resc.se)){
          resc=P(br,1);
        }
      }
    }
  }

  ll gc=__gcd(resc.fi,resc.se);
  cout<<resc.fi/gc<<"/"<<resc.se/gc<<endl;

  return 0;
}
accuracy: 0.7078651685393258
time_ms: 10
memory_kb: 3264
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

using pi = pair<int,int>;

// (行き先, 容量, コスト, 逆辺)
struct edge{ int to,cap,cost,rev; };

int V; // TODO:initialize
const int MAX_V = 100; // TODO:initialize
const int INF = 19191919; // TODO:initialize
vector<edge> G[MAX_V];
int h[MAX_V]; // ポテンシャル
int dist[MAX_V];
int prevv[MAX_V], preve[MAX_V]; // 直前の頂点と辺

void add_edge(int from, int to, int cap, int cost){
    G[from].pb({to,cap,cost,(int)G[to].size()});
    G[to].pb({from,0,-cost,(int)G[from].size()-1});
}

// sからtへの流量fの最小費用流(不可能なら-1)
int min_cost_flow(int s, int t, int f, bool neg = false){
    int res = 0;
    fill(h,h+V,0);
    while(f>0){
        priority_queue<pi,vector<pi>,greater<pi>> pq;
        fill(dist,dist+V,INF);
        dist[s]=0;
        if(neg)
        {
            // bellman-fordでhを更新
            neg = false;
            bool update;
            do{
                update = false;
                rep(v,V){
                    if(dist[v] == INF) continue;
                    rep(i,G[v].size()){
                        edge &e = G[v][i];
                        if(e.cap>0 && dist[e.to]>dist[v]+e.cost){
                            dist[e.to]=dist[v]+e.cost;
                            prevv[e.to] = v;
                            preve[e.to] = i;
                            update = true;
                        }
                    }
                }
            }while(update);
        }
        else
        {
            // dijkstraでhを更新
            pq.push(pi(0,s));
            while(!pq.empty()){
                pi p = pq.top();
                pq.pop();
                int v = p.se;
                if(p.fi>dist[v]) continue;
                rep(i,G[v].size()){
                    edge &e = G[v][i];
                    if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
                        dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        pq.push(pi(dist[e.to],e.to));
                    }
                }
            }
        }

        // これ以上流せない
        if(dist[t]==INF) return -1;

        rep(v,V) h[v] += dist[v];

        // s-t間の最短路に沿って目一杯流す
        int d=f;
        for(int v=t; v!=s; v=prevv[v]) d = min(d,G[prevv[v]][preve[v]].cap);
        f -= d;
        res += d*h[t];

        for(int v=t; v!=s; v=prevv[v]){
            edge &e = G[prevv[v]][preve[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}

using ll = __int128;
using pl = pair<ll,ll>;

pl MIN(pl a, pl b){
    if(a.fi*b.se > b.fi*a.se) return b;
    return a;
}

pl add(pl x, pl y){
    ll p = x.fi*y.se + y.fi*x.se;
    ll q = x.se*y.se;
    ll g = __gcd(p,q);
    p/=g;
    q/=g;
    return {p,q};
}

pl mul(pl x, pl y){
    ll p = x.fi*y.fi;
    ll q = x.se*y.se;
    ll g = __gcd(p,q);
    p/=g;
    q/=g;
    return {p,q};
}

pl f(ll A, ll B, ll C, pl x){
    pl res(C,1);
    res = add(res, mul(x, {2*B,1}));
    res = add(res, mul(mul(x,x),{A,1}));
    return res;
}

int main(){
    int n,m,S,T;
    scanf(" %d %d %d %d", &n, &m, &S, &T);
    --S;
    --T;
    rep(i,m){
        int a,b,u,c;
        scanf(" %d %d %d %d", &a, &b, &u, &c);
        --a;
        --b;
        add_edge(a,b,u,c);
    }

    V = n;

    ll M = 0;
    vector<int> c;
    while(1){
        int f = min_cost_flow(S,T,1);
        c.pb(f);

        if(f == -1) break;
        ++M;
    }

    pl ans(LLONG_MAX/3,1);
    if(M==0){
        ans = {0,1};
    }
    else{
        ll p = 0;
        rep(i,M){
            ll A = c[i]*c[i] + 1;
            ll B = c[i]*p - M + i;
            ll C = p*p + (M-i)*(M-i);

            pl x(0,1);
            if(B<0){
                if(-B>A) x = {1,1};
                else x = {-B,A};
            }

            ans = MIN(ans, f(A,B,C,x));
            p += c[i];
        }
    }

    printf("%lld/%lld\n", (long long)ans.fi, (long long)ans.se);
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3380
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

using pi = pair<int,int>;

// (行き先, 容量, コスト, 逆辺)
struct edge{ int to,cap,cost,rev; };

int V; // TODO:initialize
const int MAX_V = 100; // TODO:initialize
const int INF = 19191919; // TODO:initialize
vector<edge> G[MAX_V];
int h[MAX_V]; // ポテンシャル
int dist[MAX_V];
int prevv[MAX_V], preve[MAX_V]; // 直前の頂点と辺

void add_edge(int from, int to, int cap, int cost){
    G[from].pb({to,cap,cost,(int)G[to].size()});
    G[to].pb({from,0,-cost,(int)G[from].size()-1});
}

// sからtへの流量fの最小費用流(不可能なら-1)
int min_cost_flow(int s, int t, int f, bool neg = false){
    int res = 0;
    fill(h,h+V,0);
    while(f>0){
        priority_queue<pi,vector<pi>,greater<pi>> pq;
        fill(dist,dist+V,INF);
        dist[s]=0;
        if(neg)
        {
            // bellman-fordでhを更新
            neg = false;
            bool update;
            do{
                update = false;
                rep(v,V){
                    if(dist[v] == INF) continue;
                    rep(i,G[v].size()){
                        edge &e = G[v][i];
                        if(e.cap>0 && dist[e.to]>dist[v]+e.cost){
                            dist[e.to]=dist[v]+e.cost;
                            prevv[e.to] = v;
                            preve[e.to] = i;
                            update = true;
                        }
                    }
                }
            }while(update);
        }
        else
        {
            // dijkstraでhを更新
            pq.push(pi(0,s));
            while(!pq.empty()){
                pi p = pq.top();
                pq.pop();
                int v = p.se;
                if(p.fi>dist[v]) continue;
                rep(i,G[v].size()){
                    edge &e = G[v][i];
                    if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
                        dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        pq.push(pi(dist[e.to],e.to));
                    }
                }
            }
        }

        // これ以上流せない
        if(dist[t]==INF) return -1;

        rep(v,V) h[v] += dist[v];

        // s-t間の最短路に沿って目一杯流す
        int d=f;
        for(int v=t; v!=s; v=prevv[v]) d = min(d,G[prevv[v]][preve[v]].cap);
        f -= d;
        res += d*h[t];

        for(int v=t; v!=s; v=prevv[v]){
            edge &e = G[prevv[v]][preve[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}

using pl = pair<ll,ll>;
using lll = __int128;

pl MIN(pl a, pl b){
    if((lll)a.fi*b.se > (lll)b.fi*a.se) return b;
    return a;
}

pl add(pl x, pl y){
    ll p = x.fi*y.se + y.fi*x.se;
    ll q = x.se*y.se;
    ll g = __gcd(p,q);
    p/=g;
    q/=g;
    return {p,q};
}

pl mul(pl x, pl y){
    ll p = x.fi*y.fi;
    ll q = x.se*y.se;
    ll g = __gcd(p,q);
    p/=g;
    q/=g;
    return {p,q};
}

pl f(ll A, ll B, ll C, pl x){
    pl res(C,1);
    res = add(res, mul(x, {2*B,1}));
    res = add(res, mul(mul(x,x),{A,1}));
    return res;
}

int main(){
    int n,m,S,T;
    scanf(" %d %d %d %d", &n, &m, &S, &T);
    --S;
    --T;
    rep(i,m){
        int a,b,u,c;
        scanf(" %d %d %d %d", &a, &b, &u, &c);
        --a;
        --b;
        add_edge(a,b,u,c);
    }

    V = n;

    int M = 0;
    vector<int> c;
    while(1){
        int f = min_cost_flow(S,T,1);
        c.pb(f);

        if(f == -1) break;
        ++M;
    }

    pl ans(LLONG_MAX/3,1);
    ll p = 0;
    rep(i,M){
        ll A = c[i]*c[i] + 1;
        ll B = c[i]*p - M + i;
        ll C = p*p + (M-i)*(M-i);

        pl x(0,1);
        if(B<0){
            if(-B>A) x = {1,1};
            else x = {-B,A};
        }

        ans = MIN(ans, f(A,B,C,x));
        p += c[i];
    }

    printf("%lld/%lld\n", ans.fi, ans.se);
    return 0;
}
accuracy: 0.9325842696629213
time_ms: 10
memory_kb: 3336
final_rank: 15