Problem:
辺が先か，頂点が先か
2020年，世は大グラフ時代．世界は「グラフは辺から先に生まれた」と主張する辺派と，「グラフは頂点から先に生まれた」と主張する頂点派に大きく二分され，混沌を極めていた．主張をぶつけあう両派が行き着いた戦いの究極形が，グラフを用いたとある 2 人ゲームである．今日も辺派のエッジ男さんと頂点派のヴァーテックス子さんが，これからこのゲームで競い合う予定だ．
このゲームではまず
N
頂点
M
辺の有向グラフが与えられる．このゲームは 3 つのフェイズからなり，先手フェイズ，後手フェイズ，評価フェイズの順に進行する．
先手フェイズ: 先手は辺派のエッジ男さんであり，このフェイズでは
M
本の辺からちょうど 1 本の辺をランダムに選ぶための確率をエッジ男さんが設定する．すなわち，すべての辺に対し
i
番目の辺が選ばれる確率
e
i
を好きに割り振る．ここで，各
e
i
は 0 以上 1 以下の実数であり，すべての
e
i
の和はちょうど 1 でなければならない．
後手フェイズ: 後手である頂点派のヴァーテックス子さんは，
N
個の頂点からちょうど 1 つの頂点をランダムに選ぶための確率を設定する．すなわち，すべての頂点に対し
j
番目の頂点が選ばれる確率
v
j
を好きに割り振る．辺と同様，各
v
j
は 0 以上 1 以下の実数であり，すべての
v
j
の和はちょうど 1 でなければならない．ここで後手は，先手が辺に割り当てた確率を自由に見てから確率を割り振ることができる．
評価フェイズ: 割り当てられた確率に基づき，辺を 1 本と頂点を 1 つ，独立にランダムに決定する．選ばれた辺と頂点の関係によって，ゲームのスコアを以下のように決める．
頂点が有向辺の始点であれば，スコアは -1 である．
頂点が有向辺の終点であれば，スコアは 1 である．
頂点が有向辺の始点でも終点でもなければ，スコアは 0 である．
このゲームにおいて後手の頂点派のヴァーテックス子さんはスコアの期待値を最小化するように確率を割り振る．これはもちろん，頂点が辺よりも先に来るべきだと考えているからだ．一方先手の辺派のエッジ男さんは，後手のヴァーテックス子さんがスコアの期待値を最小化する戦略を取ることを踏まえた上で，スコアの期待値を最大化するように確率を割り振る．これは言わずもがな，辺が頂点よりも先に来るべきだと考えているからだ．与えられたグラフにおいて 2 人が上記の戦略に基づいて辺・頂点に確率を割り当てるとき，スコアの期待値を求めよ．
Input
入力は 50 個以下のデータセットからなる． 各データセットは次の形式で表される．
N
M
a
1
b
1
…
a
M
b
M
1 行目はゲームで用いる有向グラフの頂点数
N
(
2 ≤ N ≤ 10
4
) と辺数
M
(
1 ≤ M ≤ 10
4
) からなる．
続く
M
行はグラフの有向辺の情報を表す．
M
行のうちの
i
行目は，
i
番目の辺の始点が
a
i
(
1 ≤ a
i
≤ N
) 番目の頂点であり，終点が
b
i
(
1 ≤ b
i
≤ N
) 番目の頂点であることを表す．
与えられるグラフには自己ループがない．すなわち，すべての
1 ≤ i ≤ M
について，
a
i
≠ b
i
を満たす．
与えられるグラフには多重辺がない．すなわち，すべての
1 ≤ i < j ≤ M
について，
a
i
≠ a
j
または
b
i
≠ b
j
のいずれかを満たす．
入力の終わりは 2 つのゼロからなる行で表される．
Output
与えられたグラフにおいて，両者が上記の各々の最適な戦略を取ったときの，ゲームのスコアの期待値を 1 行に出力せよ．結果は
10
−10
以上の誤差を含んではいけない．
Sample Input
4 4
1 2
1 3
2 4
3 4
3 3
1 2
1 3
2 3
4 4
1 2
2 3
3 4
4 1
4 3
1 2
1 4
2 3
5 2
1 2
5 4
0 0
Output for the Sample Input
-0.25
-0.333333333333333
0
-0.333333333333333
-0.5

Submitted solutions:

code_snippet: // C++ includes used for precompiling -*- C++ -*-
// Copyright (C) 2003-2013 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://w...content-available-to-author-only...u.org/licenses/>.
/** @file stdc++.h
 *  This is an implementation file for a precompiled header.
 */
// 17.4.1.2 Headers
// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif
// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <unordered_set>

#endif
using namespace std;
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) v.begin(), v.end()
template <class T, class U>
inline bool chmax(T &a, U b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T, class U>
inline bool chmin(T &a, U b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
inline void compress(vector<T> &a) {
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
}
template <class T>
T rand(T l, T r) {
    static mt19937 mt(random_device{}());
    // [l, r)
    if constexpr (is_integral_v<T>) {
        return uniform_int_distribution<T>(l, r - 1)(mt);
    } else if constexpr (is_floating_point_v<T>) {
        return uniform_real_distribution<T>(l, r)(mt);
    }
}
constexpr int INF = 1001001001;
constexpr ll llINF = 3000000000000000010;
struct linear_sieve {
    vector<int> least_factor, prime_list;
    linear_sieve(int n) : least_factor(n + 1, 0) {
        for (int i = 2; i <= n; i++) {
            if (least_factor[i] == 0) {
                least_factor[i] = i;
                prime_list.push_back(i);
            }
            for (int p : prime_list) {
                if (ll(i) * p > n || p > least_factor[i]) break;
                least_factor[i * p] = p;
            }
        }
    }
};
template <int modulo>
struct modint {
    int x;
    modint() : x(0) {}
    modint(int64_t y) : x(y >= 0 ? y % modulo : (modulo - (-y) % modulo) % modulo) {}
    modint &operator+=(const modint &p) {
        if ((x += p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator-=(const modint &p) {
        if ((x += modulo - p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator*=(const modint &p) {
        x = (int)(1LL * x * p.x % modulo);
        return *this;
    }
    modint &operator/=(const modint &p) {
        *this *= p.inv();
        return *this;
    }
    modint operator-() const { return modint(-x); }
    modint operator+(const modint &p) const { return modint(*this) += p; }
    modint operator-(const modint &p) const { return modint(*this) -= p; }
    modint operator*(const modint &p) const { return modint(*this) *= p; }
    modint operator/(const modint &p) const { return modint(*this) /= p; }
    bool operator==(const modint &p) const { return x == p.x; }
    bool operator!=(const modint &p) const { return x != p.x; }
    modint inv() const {
        int a = x, b = modulo, u = 1, v = 0, t;
        while (b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return modint(u);
    }
    modint pow(int64_t n) const {
        modint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os, const modint &p) { return os << p.x; }
    friend istream &operator>>(istream &is, modint &a) {
        int64_t t;
        is >> t;
        a = modint<modulo>(t);
        return (is);
    }
    int val() const { return x; }
    static constexpr int mod() { return modulo; }
    static constexpr int half() { return (modulo + 1) >> 1; }
};
ll extgcd(ll a, ll b, ll &x, ll &y) {
    // ax+by=gcd(|a|,|b|)
    if (a < 0 || b < 0) {
        ll d = extgcd(abs(a), abs(b), x, y);
        if (a < 0) x = -x;
        if (b < 0) y = -y;
        return d;
    }
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = extgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
template <typename T>
struct Binomial {
    vector<T> inv, fact, factinv;
    Binomial(int n) {
        inv.resize(n + 1);
        fact.resize(n + 1);
        factinv.resize(n + 1);
        inv[0] = fact[0] = factinv[0] = 1;
        for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;
        factinv[n] = fact[n].inv();
        inv[n] = fact[n - 1] * factinv[n];
        for (int i = n - 1; i >= 1; i--) {
            factinv[i] = factinv[i + 1] * (i + 1);
            inv[i] = fact[i - 1] * factinv[i];
        }
    }
    T C(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r] * factinv[r];
    }
    T P(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r];
    }
    T H(int n, int r) {
        if (n == 0 && r == 0) return 1;
        if (n < 0 || r < 0) return 0;
        return r == 0 ? 1 : C(n + r - 1, r);
    }
};
template <class T>
vector<T> dijkstra(vector<vector<pair<int, T>>> &g, vector<int> start) {
    using P = pair<T, int>;
    vector<T> dp(g.size(), numeric_limits<T>::max());
    priority_queue<P, vector<P>, greater<P>> que;
    for (int s : start) {
        dp[s] = 0;
        que.push({0, s});
    }
    while (que.size()) {
        auto [d, v] = que.top();
        que.pop();
        if (dp[v] != d) continue;
        for (auto [u, c] : g[v]) {
            if (chmin(dp[u], d + c)) que.push({dp[u], u});
        }
    }
    return dp;
}

vector<int> BFS01(vector<vector<pair<int, int>>> &g, vector<int> start) {
    vector<int> dp(g.size(), numeric_limits<int>::max());
    deque<int> que;
    for (int s : start) {
        dp[s] = 0;
        que.push_front(s);
    }
    while (que.size()) {
        auto v = que.front();
        que.pop_front();
        for (auto [u, c] : g[v]) {
            if (chmin(dp[u], dp[v] + c)) {
                if (c == 0)
                    que.push_front(u);
                else
                    que.push_back(u);
            }
        }
    }
    return dp;
}
template <typename T, typename U>
inline istream &operator>>(istream &is, pair<T, U> &rhs) {
    return is >> rhs.first >> rhs.second;
}
template <typename T>
inline istream &operator>>(istream &is, vector<T> &v) {
    for (auto &e : v) is >> e;
    return is;
}
template <typename T, typename U>
inline ostream &operator<<(ostream &os, const pair<T, U> &rhs) {
    return os << rhs.first << " " << rhs.second;
}
template <typename T>
inline ostream &operator<<(ostream &os, const vector<T> &v) {
    for (auto itr = v.begin(), end_itr = v.end(); itr != end_itr;) {
        os << *itr;
        if (++itr != end_itr) os << " ";
    }
    return os;
}

struct UnionFind {
    vector<int> par, siz;
    UnionFind(int x) {
        par.resize(x);
        siz.resize(x);
        for (int i = 0; i < x; i++) {
            par[i] = i;
            siz[i] = 1;
        }
    }
    int find(int x) {
        if (par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return false;
        if (siz[x] < siz[y]) swap(x, y);
        par[y] = x;
        siz[x] += siz[y];

        return true;
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return siz[find(x)]; }
};
template <class T>
struct BIT {
    // 1-indexed
    int n, beki = 1;
    vector<T> bit;
    BIT(int x) {
        bit.resize(x + 1, 0);
        n = x;
        while (beki * 2 <= n) beki *= 2;
    }
    T sum(int i) {
        T res = 0;
        while (i > 0) {
            res += bit[i];
            i -= i & -i;
        }
        return res;
    }
    T sum(int l, int r) {
        //[l,r]
        return sum(r) - (l == 0 ? 0 : sum(l - 1));
    }
    void add(int i, T x) {
        while (i <= n) {
            bit[i] += x;
            i += i & -i;
        }
    }
    int lowerbound(T w) {
        if (w <= 0) return 0;
        int x = 0;
        for (int k = beki; k > 0; k >>= 1) {
            if (x + k <= n && bit[x + k] < w) {
                w -= bit[x + k];
                x += k;
            }
        }
        return x + 1;
    }
};
using mint = modint<998244353>;

#include <algorithm>

#include <algorithm>
#include <utility>
#include <vector>

namespace atcoder {
namespace internal {

template <class E> struct csr {
    std::vector<int> start;
    std::vector<E> elist;
    csr(int n, const std::vector<std::pair<int, E>>& edges)
        : start(n + 1), elist(edges.size()) {
        for (auto e : edges) {
            start[e.first + 1]++;
        }
        for (int i = 1; i <= n; i++) {
            start[i] += start[i - 1];
        }
        auto counter = start;
        for (auto e : edges) {
            elist[counter[e.first]++] = e.second;
        }
    }
};

struct scc_graph {
  public:
    scc_graph(int n) : _n(n) {}

    int num_vertices() { return _n; }

    void add_edge(int from, int to) { edges.push_back({from, {to}}); }

    std::pair<int, std::vector<int>> scc_ids() {
        auto g = csr<edge>(_n, edges);
        int now_ord = 0, group_num = 0;
        std::vector<int> visited, low(_n), ord(_n, -1), ids(_n);
        visited.reserve(_n);
        auto dfs = [&](auto self, int v) -> void {
            low[v] = ord[v] = now_ord++;
            visited.push_back(v);
            for (int i = g.start[v]; i < g.start[v + 1]; i++) {
                auto to = g.elist[i].to;
                if (ord[to] == -1) {
                    self(self, to);
                    low[v] = std::min(low[v], low[to]);
                } else {
                    low[v] = std::min(low[v], ord[to]);
                }
            }
            if (low[v] == ord[v]) {
                while (true) {
                    int u = visited.back();
                    visited.pop_back();
                    ord[u] = _n;
                    ids[u] = group_num;
                    if (u == v) break;
                }
                group_num++;
            }
        };
        for (int i = 0; i < _n; i++) {
            if (ord[i] == -1) dfs(dfs, i);
        }
        for (auto& x : ids) {
            x = group_num - 1 - x;
        }
        return {group_num, ids};
    }

    std::vector<std::vector<int>> scc() {
        auto ids = scc_ids();
        int group_num = ids.first;
        std::vector<int> counts(group_num);
        for (auto x : ids.second) counts[x]++;
        std::vector<std::vector<int>> groups(ids.first);
        for (int i = 0; i < group_num; i++) {
            groups[i].reserve(counts[i]);
        }
        for (int i = 0; i < _n; i++) {
            groups[ids.second[i]].push_back(i);
        }
        return groups;
    }

  private:
    int _n;
    struct edge {
        int to;
    };
    std::vector<std::pair<int, edge>> edges;
};

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <vector>

namespace atcoder {

struct scc_graph {
  public:
    scc_graph() : internal(0) {}
    scc_graph(int n) : internal(n) {}

    void add_edge(int from, int to) {
        int n = internal.num_vertices();
        assert(0 <= from && from < n);
        assert(0 <= to && to < n);
        internal.add_edge(from, to);
    }

    std::vector<std::vector<int>> scc() { return internal.scc(); }

  private:
    internal::scc_graph internal;
};

}  // namespace atcoder

void solve() {
    int n, m;
    cin >> n >> m;
    if (n == 0 && m == 0) exit(0);
    atcoder::scc_graph sg(n);
    vector<vector<int>> g(n);
    rep(i, m) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        g[b].push_back(a);
        sg.add_edge(b, a);
    }
    auto scc = sg.scc();
    if (scc.size() != n) {
        puts("0");
        return;
    }
    vector<int> dep(n);
    rep(i, n) {
        int u = scc[i][0];
        for (int v : g[u]) {
            chmax(dep[v], dep[u] + 1);
        }
    }
    printf("%.12lf\n", -1.0 / reduce(all(dep)));
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int t = 1;
    // cin >> t;
    while (1) solve();
}
accuracy: 1
time_ms: 30
memory_kb: 6328
final_rank: 9

code_snippet: // C++ includes used for precompiling -*- C++ -*-
// Copyright (C) 2003-2013 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://w...content-available-to-author-only...u.org/licenses/>.
/** @file stdc++.h
 *  This is an implementation file for a precompiled header.
 */
// 17.4.1.2 Headers
// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif
// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <unordered_set>

#endif
using namespace std;
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) v.begin(), v.end()
template <class T, class U>
inline bool chmax(T &a, U b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T, class U>
inline bool chmin(T &a, U b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
inline void compress(vector<T> &a) {
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
}
template <class T>
T rand(T l, T r) {
    static mt19937 mt(random_device{}());
    // [l, r)
    if constexpr (is_integral_v<T>) {
        return uniform_int_distribution<T>(l, r - 1)(mt);
    } else if constexpr (is_floating_point_v<T>) {
        return uniform_real_distribution<T>(l, r)(mt);
    }
}
constexpr int INF = 1001001001;
constexpr ll llINF = 3000000000000000010;
struct linear_sieve {
    vector<int> least_factor, prime_list;
    linear_sieve(int n) : least_factor(n + 1, 0) {
        for (int i = 2; i <= n; i++) {
            if (least_factor[i] == 0) {
                least_factor[i] = i;
                prime_list.push_back(i);
            }
            for (int p : prime_list) {
                if (ll(i) * p > n || p > least_factor[i]) break;
                least_factor[i * p] = p;
            }
        }
    }
};
template <int modulo>
struct modint {
    int x;
    modint() : x(0) {}
    modint(int64_t y) : x(y >= 0 ? y % modulo : (modulo - (-y) % modulo) % modulo) {}
    modint &operator+=(const modint &p) {
        if ((x += p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator-=(const modint &p) {
        if ((x += modulo - p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator*=(const modint &p) {
        x = (int)(1LL * x * p.x % modulo);
        return *this;
    }
    modint &operator/=(const modint &p) {
        *this *= p.inv();
        return *this;
    }
    modint operator-() const { return modint(-x); }
    modint operator+(const modint &p) const { return modint(*this) += p; }
    modint operator-(const modint &p) const { return modint(*this) -= p; }
    modint operator*(const modint &p) const { return modint(*this) *= p; }
    modint operator/(const modint &p) const { return modint(*this) /= p; }
    bool operator==(const modint &p) const { return x == p.x; }
    bool operator!=(const modint &p) const { return x != p.x; }
    modint inv() const {
        int a = x, b = modulo, u = 1, v = 0, t;
        while (b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return modint(u);
    }
    modint pow(int64_t n) const {
        modint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os, const modint &p) { return os << p.x; }
    friend istream &operator>>(istream &is, modint &a) {
        int64_t t;
        is >> t;
        a = modint<modulo>(t);
        return (is);
    }
    int val() const { return x; }
    static constexpr int mod() { return modulo; }
    static constexpr int half() { return (modulo + 1) >> 1; }
};
ll extgcd(ll a, ll b, ll &x, ll &y) {
    // ax+by=gcd(|a|,|b|)
    if (a < 0 || b < 0) {
        ll d = extgcd(abs(a), abs(b), x, y);
        if (a < 0) x = -x;
        if (b < 0) y = -y;
        return d;
    }
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = extgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
template <typename T>
struct Binomial {
    vector<T> inv, fact, factinv;
    Binomial(int n) {
        inv.resize(n + 1);
        fact.resize(n + 1);
        factinv.resize(n + 1);
        inv[0] = fact[0] = factinv[0] = 1;
        for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;
        factinv[n] = fact[n].inv();
        inv[n] = fact[n - 1] * factinv[n];
        for (int i = n - 1; i >= 1; i--) {
            factinv[i] = factinv[i + 1] * (i + 1);
            inv[i] = fact[i - 1] * factinv[i];
        }
    }
    T C(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r] * factinv[r];
    }
    T P(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r];
    }
    T H(int n, int r) {
        if (n == 0 && r == 0) return 1;
        if (n < 0 || r < 0) return 0;
        return r == 0 ? 1 : C(n + r - 1, r);
    }
};
template <class T>
vector<T> dijkstra(vector<vector<pair<int, T>>> &g, vector<int> start) {
    using P = pair<T, int>;
    vector<T> dp(g.size(), numeric_limits<T>::max());
    priority_queue<P, vector<P>, greater<P>> que;
    for (int s : start) {
        dp[s] = 0;
        que.push({0, s});
    }
    while (que.size()) {
        auto [d, v] = que.top();
        que.pop();
        if (dp[v] != d) continue;
        for (auto [u, c] : g[v]) {
            if (chmin(dp[u], d + c)) que.push({dp[u], u});
        }
    }
    return dp;
}

vector<int> BFS01(vector<vector<pair<int, int>>> &g, vector<int> start) {
    vector<int> dp(g.size(), numeric_limits<int>::max());
    deque<int> que;
    for (int s : start) {
        dp[s] = 0;
        que.push_front(s);
    }
    while (que.size()) {
        auto v = que.front();
        que.pop_front();
        for (auto [u, c] : g[v]) {
            if (chmin(dp[u], dp[v] + c)) {
                if (c == 0)
                    que.push_front(u);
                else
                    que.push_back(u);
            }
        }
    }
    return dp;
}
template <typename T, typename U>
inline istream &operator>>(istream &is, pair<T, U> &rhs) {
    return is >> rhs.first >> rhs.second;
}
template <typename T>
inline istream &operator>>(istream &is, vector<T> &v) {
    for (auto &e : v) is >> e;
    return is;
}
template <typename T, typename U>
inline ostream &operator<<(ostream &os, const pair<T, U> &rhs) {
    return os << rhs.first << " " << rhs.second;
}
template <typename T>
inline ostream &operator<<(ostream &os, const vector<T> &v) {
    for (auto itr = v.begin(), end_itr = v.end(); itr != end_itr;) {
        os << *itr;
        if (++itr != end_itr) os << " ";
    }
    return os;
}

struct UnionFind {
    vector<int> par, siz;
    UnionFind(int x) {
        par.resize(x);
        siz.resize(x);
        for (int i = 0; i < x; i++) {
            par[i] = i;
            siz[i] = 1;
        }
    }
    int find(int x) {
        if (par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return false;
        if (siz[x] < siz[y]) swap(x, y);
        par[y] = x;
        siz[x] += siz[y];

        return true;
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return siz[find(x)]; }
};
template <class T>
struct BIT {
    // 1-indexed
    int n, beki = 1;
    vector<T> bit;
    BIT(int x) {
        bit.resize(x + 1, 0);
        n = x;
        while (beki * 2 <= n) beki *= 2;
    }
    T sum(int i) {
        T res = 0;
        while (i > 0) {
            res += bit[i];
            i -= i & -i;
        }
        return res;
    }
    T sum(int l, int r) {
        //[l,r]
        return sum(r) - (l == 0 ? 0 : sum(l - 1));
    }
    void add(int i, T x) {
        while (i <= n) {
            bit[i] += x;
            i += i & -i;
        }
    }
    int lowerbound(T w) {
        if (w <= 0) return 0;
        int x = 0;
        for (int k = beki; k > 0; k >>= 1) {
            if (x + k <= n && bit[x + k] < w) {
                w -= bit[x + k];
                x += k;
            }
        }
        return x + 1;
    }
};
using mint = modint<998244353>;

#include <algorithm>

#include <algorithm>
#include <utility>
#include <vector>

namespace atcoder {
namespace internal {

template <class E> struct csr {
    std::vector<int> start;
    std::vector<E> elist;
    csr(int n, const std::vector<std::pair<int, E>>& edges)
        : start(n + 1), elist(edges.size()) {
        for (auto e : edges) {
            start[e.first + 1]++;
        }
        for (int i = 1; i <= n; i++) {
            start[i] += start[i - 1];
        }
        auto counter = start;
        for (auto e : edges) {
            elist[counter[e.first]++] = e.second;
        }
    }
};

struct scc_graph {
  public:
    scc_graph(int n) : _n(n) {}

    int num_vertices() { return _n; }

    void add_edge(int from, int to) { edges.push_back({from, {to}}); }

    std::pair<int, std::vector<int>> scc_ids() {
        auto g = csr<edge>(_n, edges);
        int now_ord = 0, group_num = 0;
        std::vector<int> visited, low(_n), ord(_n, -1), ids(_n);
        visited.reserve(_n);
        auto dfs = [&](auto self, int v) -> void {
            low[v] = ord[v] = now_ord++;
            visited.push_back(v);
            for (int i = g.start[v]; i < g.start[v + 1]; i++) {
                auto to = g.elist[i].to;
                if (ord[to] == -1) {
                    self(self, to);
                    low[v] = std::min(low[v], low[to]);
                } else {
                    low[v] = std::min(low[v], ord[to]);
                }
            }
            if (low[v] == ord[v]) {
                while (true) {
                    int u = visited.back();
                    visited.pop_back();
                    ord[u] = _n;
                    ids[u] = group_num;
                    if (u == v) break;
                }
                group_num++;
            }
        };
        for (int i = 0; i < _n; i++) {
            if (ord[i] == -1) dfs(dfs, i);
        }
        for (auto& x : ids) {
            x = group_num - 1 - x;
        }
        return {group_num, ids};
    }

    std::vector<std::vector<int>> scc() {
        auto ids = scc_ids();
        int group_num = ids.first;
        std::vector<int> counts(group_num);
        for (auto x : ids.second) counts[x]++;
        std::vector<std::vector<int>> groups(ids.first);
        for (int i = 0; i < group_num; i++) {
            groups[i].reserve(counts[i]);
        }
        for (int i = 0; i < _n; i++) {
            groups[ids.second[i]].push_back(i);
        }
        return groups;
    }

  private:
    int _n;
    struct edge {
        int to;
    };
    std::vector<std::pair<int, edge>> edges;
};

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <vector>

namespace atcoder {

struct scc_graph {
  public:
    scc_graph() : internal(0) {}
    scc_graph(int n) : internal(n) {}

    void add_edge(int from, int to) {
        int n = internal.num_vertices();
        assert(0 <= from && from < n);
        assert(0 <= to && to < n);
        internal.add_edge(from, to);
    }

    std::vector<std::vector<int>> scc() { return internal.scc(); }

  private:
    internal::scc_graph internal;
};

}  // namespace atcoder

void solve() {
    int n, m;
    cin >> n >> m;
    if (n == 0 && m == 0) exit(0);
    atcoder::scc_graph sg(n);
    vector<vector<int>> g(n);
    rep(i, m) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        g[b].push_back(a);
        sg.add_edge(b, a);
    }
    auto scc = sg.scc();
    if (scc.size() != n) {
        puts("0");
        return;
    }
    vector<int> dep(n);
    int sum = 0;
    rep(i, n) {
        int u = scc[i][0];
        for (int v : g[u]) {
            chmax(dep[v], dep[u] + 1);
        }
        //   if (g[u].size() == 0) //
        sum += dep[u];
    }
    printf("%.12lf\n", -1.0 / sum);
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int t = 1;
    // cin >> t;
    while (1) solve();
}
accuracy: 1
time_ms: 30
memory_kb: 6328
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct SCC{
    int n,m,cur;
    vector<vector<int>> g;
    vector<int> low,ord,id;
    SCC(int _n=0):n(_n),m(0),cur(0),g(_n),low(_n),ord(_n,-1),id(_n){}
    void resize(int _n){
        n=_n;
        g.resize(n);
        low.resize(n);
        ord.resize(n,-1);
        id.resize(n);
    }
    void add_edge(int u,int v){g[u].emplace_back(v);}
    void dfs(int v,vector<int>& used){
        ord[v]=low[v]=cur++;
        used.emplace_back(v);
        for(auto& nxt:g[v]){
            if(ord[nxt]==-1){
                dfs(nxt,used); chmin(low[v],low[nxt]);
            }
            else{
                chmin(low[v],ord[nxt]);
            }
        }
        if(ord[v]==low[v]){
            while(1){
                int add=used.back(); used.pop_back();
                ord[add]=n; id[add]=m;
                if(v==add)break;
            }
            m++;
        }
    }
    void run(){
        vector<int> used;
        rep(v,0,n)if(ord[v]==-1)dfs(v,used);
        for(auto& x:id)x=m-1-x;
    }
};

/**
 * @brief Strongly Connected Components
 */

int main() {
while(1) {
    int N, M;
    cin >> N >> M;
    if (N == 0 && M == 0) return 0;
    vector<vector<int>> G(N);
    SCC scc(N);
    rep(i,0,M) {
        int A, B;
        cin >> A >> B;
        A--, B--;
        G[A].push_back(B);
        scc.add_edge(A,B);
    }
    scc.run();
    vector<int> ord(N);
    iota(ALL(ord),0);
    sort(ALL(ord),[&](int i, int j){return scc.id[i] > scc.id[j];});
    bool check = false;
    rep(i,0,N-1) if (scc.id[ord[i]] == scc.id[ord[i+1]]) check = true;
    if (check) {
        cout << 0 << endl;
        continue;
    }
    vector<int> DP(N);
    for (int i : ord) {
        DP[i] = 0;
        for (int j : G[i]) {
            chmax(DP[i], DP[j] + 1);
        }
    }
    int ANS = 0;
    rep(i,0,N) ANS += DP[i];
    printf("%.12f\n", (double)-1.0 / (double)ANS);
}
}
accuracy: 1
time_ms: 100
memory_kb: 5464
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<vvvb> vvvvb;
typedef pair<ll,ll> pi;
typedef pair<ll,pi> ppi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define sz(A) (ll)(A.size())
#define ALL(A) A.begin(),A.end()
#define LB(A,x) (ll)(lower_bound(ALL(A),x)-A.begin())
#define UB(A,x) (ll)(upper_bound(ALL(A),x)-A.begin())
#define COU(A,x) (UB(A,x)-LB(A,x))
#define F first
#define S second
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.F<<" "<<p.S;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.F>>p.S;return is;}
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){REP(i,sz(v))os<<v[i]<<(i+1!=sz(v)?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<class T>bool chmax(T&a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T&a,T b){if(b<a){a=b;return 1;}return 0;}
const ll mod=998244353;
template<const long long int mod=998244353>
struct modint{
  using mint=modint<mod>;
  long long int x;
  modint(long long int _x=0):x(_x%mod){if(x<0)x+=mod;}
  long long int val(){return x;}
  mint&operator=(const mint&a){x=a.x;return *this;}
  mint&operator+=(const mint&a){x+=a.x;if(x>=mod)x-=mod;return *this;}
  mint&operator-=(const mint&a){x-=a.x;if(x<0)x+=mod;return *this;}
  mint&operator*=(const mint&a){x*=a.x;x%=mod;return *this;}
  friend mint operator+(const mint&a,const mint&b){return mint(a)+=b;}
  friend mint operator-(const mint&a,const mint&b){return mint(a)-=b;}
  friend mint operator*(const mint&a,const mint&b){return mint(a)*=b;}
  mint operator-()const{return mint(0)-*this;}
  mint pow(long long int n){
    if(!n)return 1;
    mint a=1;
    mint _x=x;
    while(n){
      if(n&1)a*=_x;
      _x=_x*_x;n>>=1;
    }
    return a;
  }
  mint inv(){return pow(mod-2);}
  mint&operator/=(mint&a){return *this*=a.inv();}
  friend mint operator/(const mint&a,mint b){return mint(a)/=b;}
};
using mint=modint<998244353>;
int main(){
    while(1){
        int N,M;cin>>N>>M;
        if(!N)return 0;
        vvi E(N),F(N);
        REP(i,M){
            ll u,v;cin>>u>>v;u--;v--;
            E[u].emplace_back(v);
            F[v].emplace_back(u);
        }
        {
            //topological sort
            vi cnt(N),ord;
            REP(i,N)cnt[i]=sz(F[i]);
            queue<ll>Q;
            REP(i,N)if(!cnt[i])Q.emplace(i);
            while(sz(Q)){
                ll v=Q.front();Q.pop();
                ord.emplace_back(v);
                for(auto u:E[v]){
                    cnt[u]--;
                    if(!cnt[u])Q.emplace(u);
                }
            }
            if(sz(ord)<N){cout<<0<<endl;continue;}
            vi revord(N);
            REP(i,N)revord[ord[i]]=i;
            vvi _E(N),_F(N);
            REP(v,N)for(auto u:E[v])_E[revord[v]].emplace_back(revord[u]);
            REP(v,N)for(auto u:F[v])_F[revord[v]].emplace_back(revord[u]);
            E=_E;F=_F;
        }
        vi D(N);
        RREP(i,N)for(auto j:F[i])chmax(D[j],D[i]+1);
        ll s=0;
        REP(i,N)s+=D[i];
        printf("%.20Lf\n",(ld)-1/s);
    }
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 6036
final_rank: 20

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

template < class T > vector< T >& operator++(vector< T >& a) { for(T& x : a) x++; return a; }
template < class T > vector< T >& operator--(vector< T >& a) { for(T& x : a) x--; return a; }
template < class T > vector< T >  operator++(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x++; return res; }
template < class T > vector< T >  operator--(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x--; return res; }

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

struct scc_graph {
    using size_type = int;
    size_type n;
    std::vector<std::vector<size_type>> g;

    size_type group_num;
    std::vector<size_type> ids;
    std::vector<std::vector<size_type>> scc;
    std::vector<std::vector<size_type>> dag;

    scc_graph(const size_type n) : n(n), g(n), group_num(0), ids(n) {}

    void add_edge(const size_type from, const size_type to) {
        assert(0 <= from and from < n);
        assert(0 <= to and to < n);
        g[from].push_back(to);
    }
    void add_vertex(const size_type k) {
        assert(0 <= k);
        g.resize(n + k);
        ids.resize(n + k);
        n = n + k;
    }

    void build() {
        int now_ord = 0;
        std::vector<size_type> visited, low(n), ord(n, -1);
        visited.reserve(n);
        auto dfs = [&](auto self, size_type v) -> void {
            low[v] = ord[v] = now_ord++;
            visited.push_back(v);
            for(size_type to : g[v]) {
                if(ord[to] == -1) {
                    self(self, to);
                    low[v] = std::min(low[v], low[to]);
                } else {
                    low[v] = std::min(low[v], ord[to]);
                }
            }
            if(low[v] == ord[v]) {
                while(true) {
                    size_type u = visited.back(); visited.pop_back();
                    ord[u] = n;
                    ids[u] = group_num;
                    if(u == v) break;
                }
                group_num++;
            }
        };
        for(size_type i = 0; i < n; i++) if(ord[i] == -1) dfs(dfs, i);
        for(size_type& x : ids) x = group_num - 1 - x;

        scc.resize(group_num);
        for(size_type i = 0; i < n; i++) scc[ids[i]].push_back(i);

        dag.resize(group_num);
        for(size_type from = 0; from < n; from++) {
            for(size_type to : g[from]) {
                const size_type from_id = ids[from];
                const size_type to_id = ids[to];
                if(from_id != to_id) dag[from_id].push_back(to_id);
            }
        }
    }
};

f64 solve(int N, int M) {
    scc_graph G(N);
    for(int _ : rep(M)) {
        int a = in(), b = in(); a--, b--;
        G.add_edge(a, b);
    }
    G.build();

    const int n = G.group_num;
    if(n != N) return 0.0;
    vector<vector<int>> H(n);
    vector<int> deg(n, 0);
    for(int u : rep(n)) for(int v : G.dag[u]) {
        H[v].push_back(u);
        deg[u] += 1;
    }

    vector<int> dp(n, 0);
    queue<int> q;
    for(int v : rep(n)) if(deg[v] == 0) q.push(v);
    while(not q.empty()) {
        int v = q.front(); q.pop();
        for(int to : H[v]) {
            chmax(dp[to], dp[v] + 1);
            if(--deg[to] == 0) q.push(to);
        }
    }
    int sum = 0;
    for(int i : rep(n)) sum += dp[i];
    return sum == 0 ? 0.0 : - 1.0 / sum;
}

int main() {
    while(true) {
        int N = in(), M = in();
        if(make_pair(N, M) == make_pair(0, 0)) return 0;
        printer::precision(20);
        print(solve(N, M));
    }
}
accuracy: 1
time_ms: 60
memory_kb: 6908
final_rank: 18

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

#include <algorithm>

#include <algorithm>
#include <utility>
#include <vector>

namespace atcoder {
namespace internal {

template <class E> struct csr {
    std::vector<int> start;
    std::vector<E> elist;
    csr(int n, const std::vector<std::pair<int, E>>& edges)
        : start(n + 1), elist(edges.size()) {
        for (auto e : edges) {
            start[e.first + 1]++;
        }
        for (int i = 1; i <= n; i++) {
            start[i] += start[i - 1];
        }
        auto counter = start;
        for (auto e : edges) {
            elist[counter[e.first]++] = e.second;
        }
    }
};

// Reference:
// R. Tarjan,
// Depth-First Search and Linear Graph Algorithms
struct scc_graph {
  public:
    scc_graph(int n) : _n(n) {}

    int num_vertices() { return _n; }

    void add_edge(int from, int to) { edges.push_back({from, {to}}); }

    // @return pair of (# of scc, scc id)
    std::pair<int, std::vector<int>> scc_ids() {
        auto g = csr<edge>(_n, edges);
        int now_ord = 0, group_num = 0;
        std::vector<int> visited, low(_n), ord(_n, -1), ids(_n);
        visited.reserve(_n);
        auto dfs = [&](auto self, int v) -> void {
            low[v] = ord[v] = now_ord++;
            visited.push_back(v);
            for (int i = g.start[v]; i < g.start[v + 1]; i++) {
                auto to = g.elist[i].to;
                if (ord[to] == -1) {
                    self(self, to);
                    low[v] = std::min(low[v], low[to]);
                } else {
                    low[v] = std::min(low[v], ord[to]);
                }
            }
            if (low[v] == ord[v]) {
                while (true) {
                    int u = visited.back();
                    visited.pop_back();
                    ord[u] = _n;
                    ids[u] = group_num;
                    if (u == v) break;
                }
                group_num++;
            }
        };
        for (int i = 0; i < _n; i++) {
            if (ord[i] == -1) dfs(dfs, i);
        }
        for (auto& x : ids) {
            x = group_num - 1 - x;
        }
        return {group_num, ids};
    }

    std::vector<std::vector<int>> scc() {
        auto ids = scc_ids();
        int group_num = ids.first;
        std::vector<int> counts(group_num);
        for (auto x : ids.second) counts[x]++;
        std::vector<std::vector<int>> groups(ids.first);
        for (int i = 0; i < group_num; i++) {
            groups[i].reserve(counts[i]);
        }
        for (int i = 0; i < _n; i++) {
            groups[ids.second[i]].push_back(i);
        }
        return groups;
    }

  private:
    int _n;
    struct edge {
        int to;
    };
    std::vector<std::pair<int, edge>> edges;
};

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <vector>

namespace atcoder {

struct scc_graph {
  public:
    scc_graph() : internal(0) {}
    scc_graph(int n) : internal(n) {}

    void add_edge(int from, int to) {
        int n = internal.num_vertices();
        assert(0 <= from && from < n);
        assert(0 <= to && to < n);
        internal.add_edge(from, to);
    }

    std::vector<std::vector<int>> scc() { return internal.scc(); }

  private:
    internal::scc_graph internal;
};

}  // namespace atcoder

using namespace atcoder;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vd = vector<double>;
using vvd = vector<vd>;
using vvvd = vector<vvd>;
#define all(A) A.begin(),A.end()
#define ALL(A) A.begin(),A.end()
#define rep(i, n) for (int i = 0; i < (int) (n); i++)
template<class T>
bool chmax(T& p, T q) {
    if (p < q) {
        p = q; return 1;
    }
    return 0;
};
template<class T>
bool chmin(T& p, T q) {
    if (p > q) {
        p = q; return 1;
    }
    return 0;
};


void solve(ll N,ll M) {
    scc_graph S(N);
    vector<vector<ll>> G(N);
    rep(i,M){
        ll A,B;
        cin>>A>>B;
        A--;B--;
        G[B].push_back(A);
        S.add_edge(B,A);
    }
    auto V=S.scc();
    if(V.size()!=N){
        cout<<0<<endl;
        return;
    }
    vll D(N,0);
    rep(i,N)for(auto v:G[V[i][0]])chmax(D[v],D[V[i][0]]+1);
    double an=0.0;rep(i,N)an+=double(D[i]);
    cout<<fixed<<setprecision(14)<<-1.0/an<<endl;

}

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

    ll N,M;
    while(cin>>N>>M){
        if(N==0)return 0;
        solve(N,M);
    }

}
accuracy: 1
time_ms: 40
memory_kb: 5872
final_rank: 8

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

using ll = long long;

template<class T>
bool chmax(T &a, const T &b) {if (a < b) {a = b; return 1;} return 0;}

bool is_end = false;

ll dfs(int v, vector<ll> &dist, vector<bool> &checked, const vector<vector<ll>> &rev)
{
    if (checked[v]) return dist[v];
    
    for (auto nv : rev[v])
    {
        chmax(dist[v], dfs(nv, dist, checked, rev) + 1);
    }
    checked[v] = true;
    
    return dist[v];
}

bool dfs1(int v, vector<bool> &visited, vector<bool> &done, const vector<vector<ll>> &graph)
{
    if (done[v]) return false;
    visited[v] = true;
    
    bool ret = false;
    for (auto nv : graph[v])
    {
        if (done[nv]) continue;
        if (visited[nv]) return true;
        ret |= dfs1(nv, visited, done, graph);
    }
    done[v] = true;
    
    return ret;
}

void solve()
{
    ll N, M; cin >> N >> M;
    
    if (N == 0 && M == 0)
    {
        is_end = true;
        return;
    }
    
    vector<vector<ll>> graph(N);
    vector<vector<ll>> rev(N);
    for (int i = 0; i < M; ++i)
    {
        ll u, v; cin >> u >> v;
        u--, v--;
        graph[u].emplace_back(v);
        rev[v].emplace_back(u);
    }
    
    {
        bool isnt_dag = false;
        vector<bool> visited(N, false);
        vector<bool> done(N, false);
        
        for (int i = 0; i < N; ++i)
        {
            isnt_dag |= dfs1(i, visited, done, graph);
            if (isnt_dag) break;
        }
        
        if (isnt_dag)
        {
            cout << 0 << endl;
            return;
        }
    }
    
    vector<ll> dist(N, 0);
    vector<bool> checked(N, false);
    
    for (int i = 0; i < N; ++i)
    {
        if (checked[i]) continue;
        dfs(i, dist, checked, graph);
    }
    ll sum = 0;
    for (int i = 0; i < N; ++i)
    {
        // cout << i << " " << dist[i] << endl;
        sum += dist[i];
    }
    
    cout << fixed << setprecision(20);
    cout << -(long double)1.0 / sum << endl;
    
    return;
}

int main()
{
    while (!is_end)
    {
        solve();
    }
    
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 5352
final_rank: 16

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <tuple>
#include <cstdint>
#include <cstdio>
#include <map>
#include <cstdint>
#include <queue>
#include <set>
#include <stack>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <cctype>
#include <functional>
#include <ctime>
#include <fstream>
#include <cmath>
#include <limits>
#include <chrono>
#include <numeric>
#include <type_traits>
#include <iomanip>
#include <float.h>
#include <math.h>
#include <cassert>
#include <random>

#include <cstdint>
//#include <atcoder/all>
using namespace std;
//using namespace atcoder;
using ll = long long;




ll ll_gcd(ll a, ll b) {
	if (a < b) return ll_gcd(b, a);
	ll r;
	while ((r = a % b)) {
		a = b;
		b = r;
	}
	return b;
}

long long modpow(long long a, long long n, long long mod) {
	if (n < 0)return 0;
	long long res = 1;
	while (n > 0) {
		if (n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res;
}

long long modinv(long long a, long long mod) {
	return modpow(a, mod - 2, mod);
}

ll merge_cnt(vector<ll>& a) {
	int n = a.size();
	if (n <= 1) { return 0; }

	ll cnt = 0;
	vector<ll> b(a.begin(), a.begin() + n / 2);
	vector<ll> c(a.begin() + n / 2, a.end());

	cnt += merge_cnt(b);
	cnt += merge_cnt(c);

	int ai = 0, bi = 0, ci = 0;
	while (ai < n) {
		if (bi < b.size() && (ci == c.size() || b[bi] <= c[ci])) {
			a[ai++] = b[bi++];
		}
		else {
			cnt += n / 2 - bi;
			a[ai++] = c[ci++];
		}
	}
	return cnt;
}

template< typename T >
size_t longest_increasing_subsequence(const vector< T >& a, bool strict) {
	vector< T > lis;
	for (auto& p : a) {
		typename vector< T >::iterator it;
		if (strict) it = lower_bound(begin(lis), end(lis), p);
		else it = upper_bound(begin(lis), end(lis), p);
		if (end(lis) == it) lis.emplace_back(p);
		else *it = p;
	}
	return lis.size();
}


constexpr uint32_t PrimitiveRoot(uint32_t mod) {
	using u64 = uint64_t;
	if (mod == 2) return 1;
	u64 ds[32] = {};
	int idx = 0;
	u64 m = mod - 1;
	for (u64 i = 2; i * i <= m; ++i) {
		if (m % i == 0) {
			ds[idx++] = i;
			while (m % i == 0) m /= i;
		}
	}
	if (m != 1) ds[idx++] = m;

	uint32_t pr = 2;
	while (1) {
		int flg = 1;
		for (int i = 0; i < idx; ++i) {
			u64 a = pr, b = (mod - 1) / ds[i], r = 1;
			while (b) {
				if (b & 1) r = r * a % mod;
				a = a * a % mod;
				b >>= 1;
			}
			if (r == 1) {
				flg = 0;
				break;
			}
		}
		if (flg == 1) break;
		++pr;
	}
	return pr;
}


struct edge { ll to; ll cost; };
typedef pair<ll, ll> P;
struct graph {
	ll V;
	vector<vector<edge> > G;
	vector<ll> d;

	graph(ll n) {
		init(n);
	}

	void init(ll n) {
		V = n;
		G.resize(V);
		d.resize(V);
		for (int i = 0; i < V; i++) {
			d[i] = 2000000000000000000;
		}
	}

	void add_edge(ll s, ll t, ll cost) {
		edge e;
		e.to = t, e.cost = cost;
		G[s].push_back(e);
	}

	void dijkstra(ll s) {
		for (int i = 0; i < V; i++) {
			d[i] = 2000000000000000000;
		}
		d[s] = 0;
		priority_queue<P, vector<P>, greater<P> > que;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			ll v = p.second;
			if (d[v] < p.first) continue;
			for (auto e : G[v]) {
				if (d[e.to] > d[v] + e.cost) {
					d[e.to] = d[v] + e.cost;
					que.push(P(d[e.to], e.to));
				}
			}
		}
	}
};

/*struct UnionFind {
	vector <ll> par;
	vector <ll> siz;
	UnionFind(ll sz_) : par(sz_), siz(sz_, 1LL) {
		for (ll i = 0; i < sz_; ++i) par[i] = i;
	}
	void init(ll sz_) {
		par.resize(sz_);
		siz.assign(sz_, 1LL);
		for (ll i = 0; i < sz_; ++i) par[i] = i;
	}
	ll root(ll x) {
		while (par[x] != x) {
			x = par[x] = par[par[x]];
		}
		return x;
	}
	bool merge(ll x, ll y) {
		x = root(x);
		y = root(y);
		if (x == y) return false;
		if (siz[x] < siz[y]) swap(x, y);
		siz[x] += siz[y];
		par[y] = x;
		return true;
	}

	bool issame(ll x, ll y) {
		return root(x) == root(y);
	}

	ll size(ll x) {
		return siz[root(x)];
	}
};*/




void sccdfs(vector<vector<int>>& z,int &now, vector<bool> &a,vector<int> &cnt) {
	for (int i = 0; i < z[now].size(); i++) {
		if (!a[z[now][i]]) {
			a[z[now][i]] =true;
			sccdfs(z, z[now][i], a, cnt);
		}
	}
	cnt.push_back(now);
	return;
}

void sccdfs2(vector<vector<int>>& z, int& now, vector<bool>& b, vector<int> &ans) {
	for (int i = 0; i < z[now].size(); i++) {
		if (!b[z[now][i]]) {
			b[z[now][i]] = true;
			sccdfs2(z, z[now][i], b, ans);
		}
	}
	ans.push_back(now);
	return;
}

vector<vector<int>> scc(vector<vector<int>> &z) {
	int n = z.size();
	vector<bool> a(n,false);
	vector<int> p;
	int cnt = 0;
	for (int i = 0; i < n; i++) {
		if (!a[i]){
			a[i] = true;
			sccdfs(z, i, a, p);
		}
	}
	vector<vector<int>> ans;
	vector<bool> b(n, false);
	vector<vector<int>> x(n);
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < z[i].size(); j++) {
			x[z[i][j]].push_back(i);
		}
	}
	for (int i = 0; i < n; i++) {
		if (!b[p[n-i-1]]) {
			vector<int> f;
			b[p[n - i - 1]] = true;
			sccdfs2(x, p[n - i - 1], b, f);
			ans.push_back(f);
		}
	}
	return ans;
}



int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	while (true) {
		ll n, m;
		cin >> n >> m;
		if (n == 0)break;
		vector<vector<int>> z(n);
		for (int i = 0; i < m; i++) {
			ll a, b;
			cin >> b >> a;
			a--;
			b--;
			z[a].push_back(b);
		}
		auto a = scc(z);
		if (a.size() != n) {
			cout << 0 << endl;
			continue;
		}
		vector<ll> dp(n);
		ll ans = 0;
		for (int i = 0; i < n; i++) {
			ll p = a[i][0];
			ans += dp[p];
			for (int j = 0; j < z[p].size(); j++) {
				dp[z[p][j]] = max(dp[z[p][j]], dp[p]+1);
			}
		}
		cout << fixed << setprecision(20) << (long double)((long double)-1 / (long double)(ans)) << endl;
	}
}
accuracy: 1
time_ms: 60
memory_kb: 5700
final_rank: 14

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

#define rep(i, n) for (int i = 0; i < (n); i++)
#define per(i, n) for (int i = (n)-1; i >= 0; i--)
#define rep2(i, l, r) for (int i = (l); i < (r); i++)
#define per2(i, l, r) for (int i = (r)-1; i >= (l); i--)
#define each(e, x) for (auto &e : x)
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define eb emplace_back
#define MM << ' ' <<
#define TT template <typename T>
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

TT bool chmin(T &x, T y) { return x > y ? (x = y, true) : false; }
TT bool chmax(T &x, T y) { return x < y ? (x = y, true) : false; }

TT using minheap = priority_queue<T, vector<T>, greater<T>>;
TT using maxheap = priority_queue<T>;

TT void print(vector<T> &v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    if (n == 0) cout << '\n';
}

int main() {
    while (true) {
        int N, M;
        cin >> N >> M;
        if (N == 0) break;

        vector<vector<int>> es(N);
        vector<int> deg(N, 0);

        rep(i, M) {
            int u, v;
            cin >> u >> v;
            u--, v--;
            deg[u]++;
            es[v].eb(u);
        }

        vector<bool> used(N, false);
        vector<int> ptr(N, 0);

        auto dfs = [&](auto &&dfs, int now) -> bool {
            used[now] = true;
            while (ptr[now] < sz(es[now])) {
                int k = ptr[now]++;
                int e = es[now][k];
                if (used[e]) return true;
                if (dfs(dfs, e)) return true;
            }
            used[now] = false;
            return false;
        };

        bool flag = false;

        rep(i, N) {
            if (dfs(dfs, i)) flag = true;
        }

        if (flag) {
            cout << 0 << '\n';
            continue;
        }

        vector<int> d(N, 0);
        queue<int> que;
        rep(i, N) {
            if (deg[i] == 0) que.emplace(i);
        }

        while (!empty(que)) {
            int i = que.front();
            que.pop();
            each(e, es[i]) {
                chmax(d[e], d[i] + 1);
                if (--deg[e] == 0) que.emplace(e);
            }
        }

        ll sum = 0;
        rep(i, N) sum += d[i];

        cout << fixed << setprecision(15) << -1.0 / sum << '\n';
    }
}
accuracy: 1
time_ms: 80
memory_kb: 4996
final_rank: 13

code_snippet: #include "bits/stdc++.h"
#define var auto

using namespace std;
using ll = long long;

bool solve(){
    int n, m;
    cin >> n >> m;
    if (n == 0) {
        return false;
    }
    vector edges(n, vector<int>());
    vector inc(n, 0);
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        edges[a].push_back(b);
        inc[b]++;
    }
    deque<int> deq;
    for (int i = 0; i < n; i++) {
        if (inc[i] == 0) {
            deq.push_back(i);
        }
    }
    vector<int> topo;
    while (!deq.empty()) {
        int v = deq.front();
        deq.pop_front();
        topo.push_back(v);
        for (int u : edges[v]) {
            inc[u]--;
            if (inc[u] == 0) {
                deq.push_back(u);
            }
        }
    }
    if (topo.size() < n) {
        cout << "0" << endl;
        return true;
    }
    ll sum = 0;
    vector<ll> dp(n, 0);
    for (int i = n - 1; i >= 0; i--) {
        for (int c : edges[topo[i]]) {
            dp[topo[i]] = max(dp[topo[i]], dp[c] + 1);
        }
        sum += dp[topo[i]];
    }
//    cout << sum << endl;
    printf("%.20llf\n", (long double)(-1.) / (long double)(sum));
    return true;
}

signed main(){
    while(solve());
    return false;
}
accuracy: 1
time_ms: 80
memory_kb: 4412
final_rank: 7

code_snippet: #include<iostream>
#include<string>
#include<vector>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<bitset>
// #include<atcoder/all>

using namespace std;
// using namespace atcoder;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

int main(){
	while (true) {
		int n, m;
		cin >> n >> m;
		if (n == 0 && m == 0) {
			break;
		}
		vector<vector<int>> graph(n);
		vector<int> edge_count(n, 0);
		for (int i = 0; i < m; i++) {
			int a, b;
			cin >> a >> b;
			a--; b--;
			graph[b].push_back(a);
			edge_count[a]++;
		}
		vector<int> order;
		queue<int> q;
		for (int i = 0; i < n; i++)
		{
			if (edge_count[i] == 0) q.push(i);
		}
		while (q.size() > 0) {
			int cur = q.front();
			q.pop();
			order.push_back(cur);
			for (int i = 0; i < graph[cur].size(); i++) {
				edge_count[graph[cur][i]]--;
				if (edge_count[graph[cur][i]] == 0) q.push(graph[cur][i]);
			}
		}
		if (order.size() != n) {
			cout << 0.0 << endl;
			continue;
		}
		vector<int> dp(n, 0);
		ll ansinv = 0;
		for (int i = 0; i < n; i++)
		{
			int cur = order[i];
			ansinv += dp[cur];
			for (int j = 0; j < graph[cur].size(); j++) {
				int next = graph[cur][j];
				dp[next] = max(dp[next], dp[cur] + 1);
			}
		}
		cout << fixed << setprecision(17) << -1.0 / ansinv << endl;
	}
}
accuracy: 1
time_ms: 80
memory_kb: 4204
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define foa(s, v) for(auto &s : v)
#define all(v) v.begin(), v.end()
#define REPname(a,b,c,d,...) d
#define rep(...) REPname(__VA_ARGS__, REP2, REP1, REP0)(__VA_ARGS__)
#define REP2(i,l,r) for(int i = l; i < r; i++)
#define REP1(i, x) REP2(i,0,x)
#define REP0(x) REP1(SPJ, x)
#define sz(x) int(x.size())

template <class T>
using V=vector<T>;

template <class T>
using VV=vector<V<T>>;

template<class T>
using pqmin = priority_queue<T, V<T>, greater<T>>;
using ll = long long ;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vll = vector<ll>;
using vvll = V<vll>;
constexpr ll INF = 1e18;
constexpr int inf = 1e9;
template<class T>
inline bool chmax(T &a, T b){
	return a < b ? a=b, 1 : 0;
}
template <class T>
inline bool chmin(T &a, T b) {
	return a > b ? a = b, 1 : 0;
}

template <class T>
void view(T x) {
	cerr << x;
}

template <class T>
void view(V<T> v) {
	cerr << "{ ";
	foa(t, v) {view(t) ; cerr << ", ";}
	cerr << "}";
	cerr << endl;
}


template <class T>
void view(VV<T> v) {
	cerr << "{ ";
	foa(t, v) {view(t) ; cerr << ",\n";}
	cerr << "}";
	cerr << endl;
}


// template <c0lass T>
void view(int x) {
	cerr << x;
}

#ifdef LOCAL
void debug_out() {}
template <class T>
void debug_out(T x) {
	view(x);
}
template <class H, class... T>
void debug_out(H h, T... t) {
	view(h);
	cerr << ", ";
	debug_out(t...);
}
#define debug(...)                                           \
	do {                                                     \
		cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                              \
		cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
using vvi = V<vi>;

struct uf{
	vector<int> dat;
	uf(int n) : dat(n, -1) {}
	int root(int x) 
	{
		int& p = dat[x];
		if(p < 0) return x;
		return p = root(p);
	}
	bool merge(int x, int y) {
		x = root(x);
		y = root(y);
		if(x == y) return false;
		if(-dat[x] < -dat[y]) swap(x, y);
		dat[x] += dat[y];
		dat[y]  = x;
		return true;
	}
};

ll modpow(ll x, ll n, ll md){
	ll ret = 1 % md;
	while(n > 0){
		if(n & 1) {ret *= x; ret %= md;}
		n >>= 1;
		x *= x;
		x %= md;
	}
	if(ret < 0) ret += abs(md);
	return ret;
}

double solve(int n){
	int m; cin >> m;
	vector<vi> g(n);
	vector<int> indeg(n);
	rep(m) {
		int a, b; cin >> a >> b;
		a--;
		b--;
		g[a].push_back(b);
		indeg[b]++;
	}

	queue<int> q;
	rep(i,n) if(indeg[i]==0) q.push(i);
	vector<int> tsort;
	rep(n) {
		if(q.empty()){
			return 0;
		}
		int now = q.front();
		q.pop();
		foa(e, g[now]){
			if((--indeg[e]) == 0) {
				q.push(e);
			}
		}
		tsort.push_back(now);
	}

	vector<double> path(n);
	double ans = 0;
	for(int i = n - 1; i > -1; i--){
		int now = tsort[i];
		foa(e, g[now]) {
			chmax(path[now], path[e] + 1);
		}
	}
	return -1./accumulate(all(path), 0.);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(15);
	srand((unsigned)time(NULL));
	int n;
	while(cin >> n && n) cout << solve(n) << "\n";
}
accuracy: 1
time_ms: 40
memory_kb: 4360
final_rank: 4

code_snippet: #pragma region template

#include <bits/stdc++.h>

using namespace std;

// clang-format off
using ll  = long long;    using vl   = vector<ll>;  using vvl   = vector<vl>;
using ld  = long double;  using vld  = vector<ld>;  using vvld  = vector<vld>;
using pll = pair<ll, ll>; using vpll = vector<pll>; using vvpll = vector<vpll>;
using vb = vector<bool>; using vvb = vector<vector<bool>>;
using vs = vector<string>;
using mll = map<ll, ll>;
template <class T> using V = vector<T>; template <class T> using VV = V<V<T>>; template <class T> using VVV = V<VV<T>>;
template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T>>;
constexpr ll inf = 3001001000100100100LL;
#define endl '\n'

#define  _overload(_1, _2, _3, name, ...) name
#define   rep(...) _overload(__VA_ARGS__,   _rep,   _rep2,)(__VA_ARGS__)
#define  repc(...) _overload(__VA_ARGS__,  _repc,  _repc2,)(__VA_ARGS__)
#define  repr(...) _overload(__VA_ARGS__,  _repr,  _repr2,)(__VA_ARGS__)
#define reprc(...) _overload(__VA_ARGS__, _reprc, _reprc2,)(__VA_ARGS__)
#define   _rep(i,k,n) for(ll i=(k)  , i##_xxxx=(n); i < i##_xxxx; ++i)
#define  _repc(i,k,n) for(ll i=(k)  , i##_xxxx=(n); i <=i##_xxxx; ++i)
#define  _repr(i,k,n) for(ll i=(n)-1, i##_xxxx=(k); i >=i##_xxxx; --i)
#define _reprc(i,k,n) for(ll i=(n)  , i##_xxxx=(k); i >=i##_xxxx; --i)
#define   _rep2(i,n)   _rep(i,0,n)
#define  _repc2(i,n)  _repc(i,1,n)
#define  _repr2(i,n)  _repr(i,0,n)
#define _reprc2(i,n) _reprc(i,1,n)

#define rall(o) rbegin(o), rend(o)
#define  all(o)  begin(o),  end(o)
template <class C> ll sz(const C& c) { return static_cast<ll>(c.size()); }
template <class T, class U> common_type_t<T, U> min(const T& a, const U& b){ return std::min<common_type_t<T, U>>(a,b); }
template <class T, class U> common_type_t<T, U> max(const T& a, const U& b){ return std::max<common_type_t<T, U>>(a,b); }
template <class T, class U> bool chmax(T& m, const U& v){ assert(numeric_limits<T>::max() > v); if (m < v){ m = v; return true; } return false; }
template <class T, class U> bool chmin(T& m, const U& v){ assert(numeric_limits<T>::min() < v); if (v < m){ m = v; return true; } return false; }
template <class T, class U> common_type_t<T, U> cdiv(const T& a, const U& b){ return (a + b - 1) / b; }
template <class T, class U> common_type_t<T, U> rdiv(const T& a, const T& b){ return (a + b / 2) / b; }

template <class T, class S>             string join(const T& v, const S& sep                  ){ stringstream ss; bool f = false; for (const auto& e : v){ if (f) ss << sep; f = true; ss << e;} return ss.str(); }
template <class T, class S, class... U> string join(const T& v, const S& sep, const U& ...args){ stringstream ss; bool f = false; for (const auto& c : v){ if (f) ss << sep; f = true; ss << join(c, args...); } return ss.str(); }
template <class T>            ostream& operator<<(ostream& os, const vector<T>&            seq){ os << '[' << join(seq, ",") << ']'; return os; } template <class T>            ostream& operator<<(ostream& os, const vector<vector<T>>&    seq){ os << '[' << join(seq, ",\n ") << ']'; return os; }
template <class T>            ostream& operator<<(ostream& os, const deque<T>&             seq){ os << '[' << join(seq, ",") << ']'; return os; }
template <class T>            ostream& operator<<(ostream& os, const set<T>&               seq){ os << '{' << join(seq, ",") << '}'; return os; }
template <class T , class TH> ostream& operator<<(ostream& os, const unordered_set<T, TH>& seq){ os << '{' << join(seq, ",") << '}'; return os; }
template <class TK, class TV> ostream& operator<<(ostream& os, const map<TK, TV>&          seq){ os << '{'; bool f = false; for (const auto& e : seq){ if (f) os << ','; f = true; os << e.first << ":" << e.second; } os << '}'; return os; }
template <class T1, class T2> ostream& operator<<(ostream& os, const pair<T1, T2>&          pa){ os << '(' << pa.first << ',' << pa.second << ')'; return os; }

#if LOCAL
#define debug(...) _debug(__VA_ARGS__, __LINE__)
#else
#define debug(...)
#endif
void print() { std::cout << '\n'; }
template <class S>             void  print(const S& a){ std::cout << a << '\n'; }
template <class S>             void _debug(const S& a){ std::cerr << "(L:" << std::setw(3) << a << ")\n"; }
template <class S, class... T> void  print(const S& a, const T&... args){ std::cout << a << ' ';  print(args...); }
template <class S, class... T> void _debug(const S& a, const T&... args){ std::cerr << a << ' '; _debug(args...); }

struct setup_main { setup_main() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); std::cout << fixed << setprecision(15); } } setup_main_;
// clang-format on
#pragma endregion

/*/ 考察メモ
入次数0の頂点の期待値をxとして、辺の選ばれる確率の総和が0になるように、xでつじつま合わせをする
/*/


// 閉路が存在するか
bool exist_loop(ll N, vvl G) {
    vl visited(N, -1);

    function<ll(ll)> dfs = [&](ll at) {
        if (visited[at] == 1) return false;
        if (visited[at] == 2) return true;

        visited[at] = 2;
        bool flag = false;
        for (auto&& to : G[at]) {
            flag |= dfs(to);
        }
        visited[at] = 1;
        return flag;
    };

    rep(i, N) {
        if (visited[i] == -1) {
            if (dfs(i)) return true;
        }
    }
    return false;
}


// DAGに対して各頂点から行ける最も遠い頂点までの距離を返す
vl get_max_dist(ll N, vvl& G) {
    vl dist(N, 0);
    vl visited(N, 0);
    function<ll(ll)> dfs = [&](ll at) {
        if (visited[at]) return dist[at];
        visited[at] = true;

        ll d = 0;
        for (auto&& to : G[at]) {
            chmax(d, dfs(to) + 1);
        }
        return dist[at] = d;
    };
    rep(i, N) dfs(i);

    return dist;
}


ld solve(ll N, vvl G) {
    if (exist_loop(N, G)) return 0;
    vl max_dist = get_max_dist(N, G);
    debug(max_dist);

    ll s = accumulate(all(max_dist), 0LL);
    return -(ld)1 / s;
}


signed main() {
    while (true) {
        ll N, M;
        cin >> N >> M;

        if (N == 0) break;

        vvl G(N);
        rep(i, M) {
            ll a, b;
            cin >> a >> b;
            a--, b--; // 0-based
            G[a].emplace_back(b);
        }

        print(solve(N, G));
    }
}
accuracy: 1
time_ms: 50
memory_kb: 5864
final_rank: 12

code_snippet: #include<deque>
#include<queue>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
#include<cmath>
#include<tuple>
#include<string>
#include<chrono>
#include<functional>
#include<iterator>
#include<random>
#include<unordered_set>
#include<array>
#include<map>
#include<iomanip>
#include<assert.h>
#include<list>
#include<bitset>
#include<stack>
#include<memory>
#include<numeric>
#include<complex>
using namespace std;
using namespace std::chrono;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase

/*cout<<fixed<<setprecision(20);cin.tie(0);ios::sync_with_stdio(false);*/
const llint mod=1000000007;
const llint inf=2.19e15+1;
const long double pai=3.141592653589793238462643383279502884197;
const long double eps=1e-10;
template <class T,class U>bool chmin(T& a,U b){if(a>b){a=b;return true;}return false;}
template <class T,class U>bool chmax(T& a,U b){if(a<b){a=b;return true;}return false;}
llint gcd(llint a,llint b){if(a%b==0){return b;}else return gcd(b,a%b);}
llint lcm(llint a,llint b){if(a==0){return b;}return a/gcd(a,b)*b;}
template<class T> void SO(T& ve){sort(ve.begin(),ve.end());}
template<class T> void REV(T& ve){reverse(ve.begin(),ve.end());}
template<class T>llint LBI(const vector<T>&ar,T in){return lower_bound(ar.begin(),ar.end(),in)-ar.begin();}
template<class T>llint UBI(const vector<T>&ar,T in){return upper_bound(ar.begin(),ar.end(),in)-ar.begin();}


int main(void){
	cout<<fixed<<setprecision(20);cin.tie(0);ios::sync_with_stdio(false);
	while(-1){
		int n,m,i;cin>>n>>m;
		if(n==0){return 0;}
		vector<int>zi(n);
		vector<int>dis(n);
		vector<vector<int>>rev(n);
		for(i=0;i<m;i++){
			int a,b;cin>>a>>b;
			a--;b--;
			zi[a]++;
			rev[b].pub(a);
		}
		queue<int>que;
		for(i=0;i<n;i++){
			if(zi[i]==0){que.push(i);}
		}
		while(que.size()){
			int t=que.front();
			que.pop();
			for(auto it:rev[t]){
				chmax(dis[it],dis[t]+1);
				zi[it]--;
				if(zi[it]==0){que.push(it);}
			}
		}
		bool zero=false;
		
		llint wa=0;
		for(i=0;i<n;i++){
			if(zi[i]!=0){zero=true;break;}
			wa+=dis[i];
		}
		if(zero){cout<<0<<endl;}
		else{cout<<-1.0/wa<<endl;}
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4328
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define _GLIBCXX_DEBUG
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=1167167167167167167;
const int INF=2100000000;
const ll mod=1e9+7;
#define rep(i,a) for (ll i=0;i<a;i++)
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}

namespace po167{
struct SCC{
	std::vector<std::vector<int>> G;
	std::vector<std::vector<int>> G_rev;
	int size;
	SCC(int n):size(n),G(n),G_rev(n){}

	void add_edge(int from,int to){
		assert(0<=to&&to<size);
		assert(0<=from&&from<size);
		G[from].push_back(to);
		G_rev[to].push_back(from);
	}

	void dfs1(std::vector<int> &order,std::vector<int> &seen,int ind,int &now){
		if(seen[ind]!=0) return;
		seen[ind]=-1;
		for(auto x:G[ind]){
			dfs1(order,seen,x,now);
		}
		order[now]=ind;
		now++;
	}
	void dfs2(std::vector<int> &seen,int ind,int rank){
		if(seen[ind]!=-1) return;
		seen[ind]=rank;
		for(auto x:G_rev[ind]){
			dfs2(seen,x,rank);
		}
	}
	std::vector<std::vector<int>> tp_sort(){
		std::vector<int> seen(size,0),order(size);
		int now=0;
		for(int i=0;i<size;i++) dfs1(order,seen,i,now);
		now=0;
		for(int i=size-1;i>=0;i--){
			if(seen[order[i]]==-1){
				dfs2(seen,order[i],now);
				now++;
			}
		}
		std::vector<std::vector<int>> ans(now);
		for(int i=0;i<size;i++){
			ans[seen[i]].push_back(i);
		}
		return ans;
	}
	std::vector<int> for_two_sat(){
		std::vector<int> seen(size,0),order(size);
		int now=0;
		for(int i=0;i<size;i++) dfs1(order,seen,i,now);
		now=0;
		for(int i=size-1;i>=0;i--){
			if(seen[order[i]]==-1){
				dfs2(seen,order[i],now);
				now++;
			}
		}
		return seen;
	}
};

struct two_SAT{
	po167::SCC graph;
	std::vector<bool> ans;
	bool exists=false;
	int size;
	two_SAT(int n):size(n),ans(n),graph(2*n){}
	void add_clause(int i,bool f,int j,bool g){
		graph.add_edge(i+size*(!f),j+size*(g));
		graph.add_edge(j+size*(!g),i+size*(f));
	}
	bool build(){
		auto rank=graph.for_two_sat();
		exists=true;
		for(int i=0;i<size;i++){
			if(rank[i]==rank[i+size]){
				exists=false;
				break;
			}
			ans[i]=(rank[i]<rank[i+size]);
		}
		return exists;
	}
};
}
using po167::SCC;
using po167::two_SAT;



void solve(int n,int m);

//  rainy ~ 雨に打たれて ~
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int n,m;
	while(cin>>n>>m,n) solve(n,m);
}

void solve(int n,int m){
	SCC S(n);
	rep(i,m){
		int a,b;
		cin>>a>>b;
		S.add_edge(a-1,b-1);
	}
	auto p=S.tp_sort();
	if(p.size()!=n){
		cout<<"0\n";
		return ;
	}
	vector<int> dist(n,0);
	int ans=0;
	rep(i,n){
		int a=p[n-i-1][0];
		//cout<<a+1<<" "<<dist[a]<<"\n";
		ans+=dist[a];
		for(auto x:S.G_rev[a]){
			chmax(dist[x],dist[a]+1);
		}
	}
	cout<<fixed<<setprecision(20);
	cout<<(ld)-1/(ld)(ans)<<"\n";
}
accuracy: 1
time_ms: 50
memory_kb: 5740
final_rank: 11

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

struct TopologicalSort {
    std::vector<std::vector<int>> G;

    TopologicalSort(int n) : G(n), n(n), indeg(n, 0) {}

    void add_edge(int u, int v) {
        assert(0 <= u && u < n);
        assert(0 <= v && v < n);
        G[u].emplace_back(v);
        indeg[v]++;
    }

    std::vector<int> build() {
        std::queue<int> que;
        for (int i = 0; i < n; i++) {
            if (indeg[i] == 0) {
                que.emplace(i);
            }
        }
        std::vector<int> order;
        while (!que.empty()) {
            int v = que.front();
            que.pop();
            order.emplace_back(v);
            for (int& u : G[v]) {
                if (--indeg[u] == 0) {
                    que.emplace(u);
                }
            }
        }
        if (*max_element(indeg.begin(), indeg.end()) != 0) return {};
        return order;
    }

private:
    int n;
    std::vector<int> indeg;
};

/**
 * @brief Topological Sort
 * @docs docs/graph/TopologicalSort.md
 */

const int INF = 1e9;

void solve(int N, int M) {
    TopologicalSort TS(N);
    vector<int> a(M), b(M);
    for (int i = 0; i < M; i++) {
        cin >> a[i] >> b[i];
        TS.add_edge(--b[i], --a[i]);
    }

    auto ord = TS.build();
    if (ord.empty()) {
        cout << 0 << '\n';
        return;
    }

    auto& G = TS.G;
    vector<int> dp(N, -1);
    for (int i = 0; i < N; i++) {
        int v = ord[i];
        if (dp[v] == -1) dp[v] = 0;
        for (int& u : G[v]) dp[u] = max(dp[u], dp[v] + 1);
    }

    int sum = accumulate(dp.begin(), dp.end(), 0);
    double ans = -1.0 / sum;
    cout << ans << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    for (int N, M; cin >> N >> M, N;) solve(N, M);
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4320
final_rank: 1

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

#include <cassert>
#include <queue>
#include <vector>

struct TopologicalSort {
    std::vector<std::vector<int>> G;

    TopologicalSort(int n) : G(n), n(n), indeg(n, 0) {}

    void add_edge(int u, int v) {
        assert(0 <= u && u < n);
        assert(0 <= v && v < n);
        G[u].emplace_back(v);
        indeg[v]++;
    }

    std::vector<int> build() {
        std::queue<int> que;
        for (int i = 0; i < n; i++) {
            if (indeg[i] == 0) {
                que.emplace(i);
            }
        }
        std::vector<int> order;
        while (!que.empty()) {
            int v = que.front();
            que.pop();
            order.emplace_back(v);
            for (int& u : G[v]) {
                if (--indeg[u] == 0) {
                    que.emplace(u);
                }
            }
        }
        if (*max_element(indeg.begin(), indeg.end()) != 0) return {};
        return order;
    }

private:
    int n;
    std::vector<int> indeg;
};

/**
 * @brief Topological Sort
 * @docs docs/graph/TopologicalSort.md
 */

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

void solve(int N, int M) {
    TopologicalSort TS(N);
    vector<int> a(M), b(M);
    for (int i = 0; i < M; i++) {
        cin >> a[i] >> b[i];
        TS.add_edge(--b[i], --a[i]);
    }

    auto ord = TS.build();
    if (ord.empty()) {
        cout << 0 << '\n';
        return;
    }

    auto& G = TS.G;
    vector<int> dp(N, -INF);
    for (int i = 0; i < N; i++) {
        int v = ord[i];
        if (dp[v] == -INF) dp[v] = 0;
        for (int& u : G[v]) chmax(dp[u], dp[v] + 1);
    }

    int sum = accumulate(ALL(dp), 0);
    double ans = -double(1) / sum;
    // vector<double> w(N);
    // for (int i = 0; i < N; i++) w[i] = double(dp[i]) / sum;
    // double ans = -INF;
    // for (int i = 0; i < M; i++) chmax(ans, w[b[i]] - w[a[i]]);
    cout << ans << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    for (int N, M; cin >> N >> M, N;) solve(N, M);
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4260
final_rank: 3

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

#include <cassert>
#include <queue>
#include <vector>

struct TopologicalSort {
    std::vector<std::vector<int>> G;

    TopologicalSort(int n) : G(n), n(n), indeg(n, 0) {}

    void add_edge(int u, int v) {
        assert(0 <= u && u < n);
        assert(0 <= v && v < n);
        G[u].emplace_back(v);
        indeg[v]++;
    }

    std::vector<int> build() {
        std::queue<int> que;
        for (int i = 0; i < n; i++) {
            if (indeg[i] == 0) {
                que.emplace(i);
            }
        }
        std::vector<int> order;
        while (!que.empty()) {
            int v = que.front();
            que.pop();
            order.emplace_back(v);
            for (int& u : G[v]) {
                if (--indeg[u] == 0) {
                    que.emplace(u);
                }
            }
        }
        if (*max_element(indeg.begin(), indeg.end()) != 0) return {};
        return order;
    }

private:
    int n;
    std::vector<int> indeg;
};

/**
 * @brief Topological Sort
 * @docs docs/graph/TopologicalSort.md
 */

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

void solve(int N, int M) {
    TopologicalSort TS(N);
    vector<int> a(M), b(M);
    for (int i = 0; i < M; i++) {
        cin >> a[i] >> b[i];
        TS.add_edge(--b[i], --a[i]);
    }

    auto ord = TS.build();
    if (ord.empty()) {
        cout << 0 << '\n';
        return;
    }

    auto& G = TS.G;
    vector<int> dp(N, -INF);
    for (int i = 0; i < N; i++) {
        int v = ord[i];
        if (dp[v] == -INF) dp[v] = 0;
        for (int& u : G[v]) chmax(dp[u], dp[v] + 1);
    }

    int sum = accumulate(ALL(dp), 0);
    vector<double> w(N);
    for (int i = 0; i < N; i++) w[i] = double(dp[i]) / sum;
    double ans = -INF;
    for (int i = 0; i < M; i++) chmax(ans, w[b[i]] - w[a[i]]);
    cout << ans << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    for (int N, M; cin >> N >> M, N;) solve(N, M);
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4376
final_rank: 5

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <set>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>
#include <random>
#include <sstream>
#include <bitset>
#include <complex>
#include <chrono>
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

std::vector<int> dag(const std::vector<std::vector<int>> &nodes) {
	int time{ 0 };
	std::vector<int> out_time(nodes.size(), -1);
	std::stack<int> stack; 
	for (auto root = 0; root < nodes.size(); ++root) {
		if (out_time[root] != -1) continue;
		stack.push(root);
		while (!stack.empty()) {
			const auto top = stack.top(); stack.pop();
			if (top >= 0) {
				if (out_time[top] != -1) continue;
				out_time[top] = 0;
				stack.push(-1 - top);
				for (const auto next : nodes[top]) {
					stack.push(next);
				}
			}
			else {
				out_time[-1 - top] = ++time;
			}
		}
	}
	std::vector<int> indices(nodes.size()); std::iota(indices.begin(), indices.end(), 0);
	std::sort(indices.begin(), indices.end(), [&out_time](const int i, const int j) {return out_time[i] > out_time[j]; });
	std::vector<std::vector<int>> reverse(nodes.size());
	for (auto from = 0; from < nodes.size(); ++from) {
		for (const auto to : nodes[from]) {
			reverse[to].push_back(from);
		}
	}
	std::vector<int> result(nodes.size(), -1);
	time = 0;
	for (const auto root : indices) {
		if (result[root] != -1) continue;
		result[root] = time;
		stack.push(root);
		while (!stack.empty()) {
			const auto top = stack.top(); stack.pop();
			for (const auto next : reverse[top]) {
				if (result[next] != -1) continue;
				result[next] = time;
				stack.push(next);
			}
		}
		++time;
	}
	return result;
}
double solve(const int n, const std::vector<std::pair<int, int>> edges) {
	std::vector<std::vector<int>> nodes(n);
	for (const auto [from, to] : edges) {
		nodes[from].push_back(to);
	}
	const auto topological_rank = dag(nodes);
	std::vector<int> topological_order(n); std::iota(topological_order.begin(), topological_order.end(), 0);
	std::sort(topological_order.begin(), topological_order.end(), [&topological_rank](const int i, const int j) {return topological_rank[i] > topological_rank[j]; });
	if (topological_rank[topological_order.front()] + 1 < n) {
		return 0;
	}
	std::vector<int> max_path(n);
	for (const auto node : topological_order) {
		for (const auto next : nodes[node]) {
			max_path[node] = std::max(max_path[node], max_path[next] + 1);
		}
	}
	const auto sum_path = std::accumulate(max_path.begin(), max_path.end(), 0LL);
	return -1.0 / sum_path;
}
int main() {
	while (true) {
		int n, m; std::cin >> n >> m;
		if (n == 0 && m == 0) break;
		std::vector<std::pair<int, int>> edges(m);
		for (auto& [a, b] : edges) {
			std::cin >> a >> b; --a; --b;
		}
		const auto result = solve(n, edges);
		std::cout << std::setprecision(15) << std::fixed << result << '\n';
	}
}
accuracy: 1
time_ms: 110
memory_kb: 4652
final_rank: 15

code_snippet: // clang-format off
#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
using ld = long double;
using Pi = pair<int, int>;
using Pl = pair<ll, ll>;
using Vi = vector<int>;
using Vl = vector<ll>;
#define FOR(i, m, n) for(int i = (m); i < (n); ++i)
#define FORR(i, m, n) for(int i = (m)-1; i >= (n); --i)
#define rep(i, n) FOR(i, 0, n)
#define repn(i, n) FOR(i, 1, n+1)
#define repr(i, n) FORR(i, n, 0)
#define repnr(i, n) FORR(i, n+1, 1)
#define all(s) (s).begin(), (s).end()
template <class T, class U>
bool chmax(T &a, const U b) { return a < b ? a = b, true : false; }
template <class T, class U>
bool chmin(T &a, const U b) { return b < a ? a = b, true : false; }
template <class T>
istream &operator>>(istream &is, vector<T> &v) { for (T &i : v) is >> i; return is; }
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) (it == v.begin() ? os : os << ' ') << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head&& head, Tail&&... tail) {
    if constexpr(sizeof...(tail)==0) cout<<head<<'\n'; else cout<<head<<' ',co(forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head&& head, Tail&&... tail) {
    if constexpr(sizeof...(tail)==0) cerr<<head<<'\n'; else cerr<<head<<' ',ce(forward<Tail>(tail)...);
}
template<typename T, typename... Args>
auto make_vector(T x, int arg, Args ...args) {
    if constexpr(sizeof...(args)==0) return vector<T>(arg, x); else return vector(arg,make_vector<T>(x, args...));
}
void sonic() { ios::sync_with_stdio(false); cin.tie(nullptr); }
void setp(const int n) { cout << fixed << setprecision(n); }
constexpr int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr int MOD = 1000000007;
constexpr int MOD_N = 998244353;
constexpr double EPS = 1e-7;
const double PI = acos(-1);

template <class T>
struct Graph {
    struct edge {
        int from, to;
        T dist;

        bool operator<(const edge &rhs) const { return dist < rhs.dist; }
        bool operator>(const edge &rhs) const { return rhs < *this; }
    };

    int V;
    vector<vector<edge>> edges;

    Graph(int v) : V(v), edges(v) {}

    const auto &operator[](int i) const { return edges[i]; }
    auto &operator[](int i) { return edges[i]; }
    const auto begin() const { return edges.begin(); }
    auto begin() { return edges.begin(); }
    const auto end() const { return edges.end(); }
    auto end() { return edges.end(); }

    int size() const { return V; }

    void add_edge(int a, int b, T d = T(1)) {
        edges[a].push_back(edge{a, b, d});
    }
    void add_edges(int a, int b, T d = T(1)) {
        edges[a].push_back(edge{a, b, d});
        edges[b].push_back(edge{b, a, d});
    }
};

template <class T>
vector<int> scc(const Graph<T> &g) {
    int n = g.size();
    Graph<T> rg(n);
    vector<int> comp(n, -1), order;
    bitset<1 << 20> used;

    for (auto &es : g) {
        for (auto &e : es) rg.add_edge(e.to, e.from);
    }

    auto dfs = [&](auto self, int idx) {
        if (used[idx]) return;
        used.set(idx);
        for (auto &e : g[idx]) self(self, e.to);
        order.emplace_back(idx);
    };
    auto rdfs = [&](auto self, int idx, int cnt) {
        if (~comp[idx]) return;
        comp[idx] = cnt;
        for (auto &e : rg[idx]) self(self, e.to, cnt);
    };

    for (int i = 0; i < n; i++) dfs(dfs, i);
    reverse(order.begin(), order.end());
    int ptr = 0;
    for (auto i : order) {
        if (comp[i] == -1) rdfs(rdfs, i, ptr++);
    }

    return comp;
};

template <class T>
Graph<T> make_DAG(const Graph<T> &g, const vector<int> &v) {
    int n = *max_element(v.begin(), v.end()) + 1;
    Graph<T> res(n);
    for (auto &es : g) {
        for (auto &e : es) {
            int x = v[e.from], y = v[e.to];
            if (x != y) res.add_edge(y, x, e.dist);
        }
    }
    return res;
}

// clang-format on

int main(void) {
    while (true) {
        int n, m;
        cin >> n >> m;
        if ((n | m) == 0)
            break;
        Graph<int> g(n);
        rep(i, m) {
            int a, b;
            cin >> a >> b;
            --a, --b;
            g.add_edge(a, b);
        }
        auto v = scc(g);
        auto h = make_DAG(g, v);
        if (h.size() != g.size()) {
            co(0);
            continue;
        }

        Vi dp(h.size(), 0);
        repr(i, h.size()) {
            for (auto &e : h[i]) {
                chmax(dp[e.to], dp[e.from] + 1);
            }
        }

        int s = accumulate(all(dp), 0);
        setp(15);
        co((long double)-1 / s);
    }

    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 5392
final_rank: 19