Problem:
Problem G:
Strange Couple
Alice and Bob are going to drive from their home to a theater for a date. They are very challenging - they have no maps with them even though they don’t know the route at all (since they have just moved to
their new home). Yes, they will be going just by their feeling.
The town they drive can be considered as an undirected graph with a number of intersections (vertices)
and roads (edges). Each intersection may or may not have a sign. On intersections with signs, Alice and
Bob will enter the road for the shortest route. When there is more than one such roads, they will go into
one of them at random.
On intersections without signs, they will just make a random choice. Each random selection is made with
equal probabilities. They can even choose to go back to the road they have just come along, on a random
selection.
Calculate the expected distance Alice and Bob will drive before reaching the theater.
Input
The input consists of multiple datasets. Each dataset has the following format:
n s t
q
1
q
2
...
q
n
a
11
a
12
...
a
1
n
a
21
a
22
...
a
2
n
.
.
.
a
n
1
a
n
2
...
a
nn
n
is the number of intersections (
n
≤ 100).
s
and
t
are the intersections the home and the theater are
located respectively (1 ≤
s
,
t
≤
n
,
s
≠
t
);
q
i
(for 1 ≤
i
≤
n
) is either 1 or 0, where 1 denotes there is a
sign at the
i
-th intersection and 0 denotes there is not;
a
ij
(for 1 ≤
i
,
j
≤
n
) is a positive integer denoting
the distance of the road connecting the
i
-th and
j
-th intersections, or 0 indicating there is no road directly
connecting the intersections. The distance of each road does not exceed 10.
Since the graph is undirectional, it holds
a
ij
=
a
ji
for any 1 ≤
i
,
j
≤
n
. There can be roads connecting the
same intersection, that is, it does
not
always hold
a
ii
= 0. Also, note that the graph is not always planar.
The last dataset is followed by a line containing three zeros. This line is not a part of any dataset and should not be processed.
Output
For each dataset, print the expected distance accurate to 10
-8
, or "
impossible
" (without quotes) if there is no route to get
to the theater. The distance may be printed with any number of digits after the decimal point.
Sample Input
5 1 5
1 0 1 0 0
0 2 1 0 0
2 0 0 1 0
1 0 0 1 0
0 1 1 0 1
0 0 0 1 0
0 0 0
Output for the Sample Input
8.50000000

Submitted solutions:

code_snippet: #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define INF 0x3f3f3f3f
#define N 110
#define eps 1e-15
#define LL long long
using namespace std;
int n, s, t, q[N];

int d[N][N], w[N][N];
void Floyd(){
	for(int k = 1; k <= n; k ++){
		for(int i = 1; i <= n; i ++){
			for(int j = 1; j <= n; j ++){
				d[i][j] = min(d[i][k] + d[k][j], d[i][j]);
			}
		}
	}
}

double a[N][N], x[N];
void Gause(){
	int i, j, k;

	for(i = 1, j = 1; i <= n && j <= n; i ++, j ++){
		int max_r = i;
		for(k = i + 1; k <= n; k ++){
			if(fabs(a[max_r][j]) < fabs(a[k][j])) max_r = k;
		}
		if(max_r != i){
			for(k = j; k <= n + 1; k ++) swap(a[i][k], a[max_r][k]);
		}
		if(fabs(a[i][j]) < eps){
			i --;
			continue;
		}
		for(k = i + 1; k <= n; k ++){
			if(fabs(a[k][j]) < eps) continue;
			double tmp = a[k][j] / a[i][j];
			for(int p = j; p <= n + 1; p ++)
				a[k][p] -= a[i][p] * tmp;
		}
	}
	
	while(-- i){
		double tmp = a[i][n + 1];
		for(int j = 1; j <= n; j ++) tmp -= x[j] * a[i][j];
		x[i] = tmp / a[i][i];
	}
}

void solve(){
	for(int i = 1; i <= n; i ++) scanf("%d", &q[i]);
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= n; j ++){
			scanf("%d", &w[i][j]);
			if(w[i][j]) d[i][j] = w[i][j];
		}
	}
	
	for(int i = 1; i <= n; i ++) d[i][i] = 0;
	
	Floyd();
	
	if(d[s][t] >= INF){
		puts("impossible");
		return;
	}
	
	
	for(int i = 1; i <= n; i++)
	{
		if(i == t)
		{
			for(int j = 1; j <= n + 1; j++) if(i ^ j) a[i][j] = 0;
			a[i][i] = 1;
		}
		else if(q[i] == 0)
		{
			int outd = 0, sum = 0;
			for(int j = 1; j <= n; j++) if(w[i][j])
			{
				outd++;
				a[i][j] = 1;
				sum += w[i][j];
			}
			a[i][i] -= outd;
			a[i][n + 1] = -sum;
		}
		else
		{
			int outd = 0, sum = 0;
			for(int j = 1; j <= n; j++) if(w[i][j]) if(d[j][t] + w[i][j] == d[i][t])
			{
				outd++;
				a[i][j] = 1;
				sum += w[i][j];
			}
			a[i][i] -= outd;
			a[i][n + 1] = -sum;
		}
	}
	
	Gause();
	
	printf("%.10f\n", x[s]);
}

void init(){
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= n; j ++){
			w[i][j] = 0;
			a[i][j] = 0;
			d[i][j] = INF;	
		}
		x[i] = 0;
	}
}

int main(){
	for(int i = 1;scanf("%d%d%d", &n, &s, &t) == 3; i ++){
		if(!n && !s && !t) break;
		init();
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3588
final_rank: 1

code_snippet: // AOJ #2171
// Strange Couple 2025.2.10

#include <bits/stdc++.h>
using namespace std;
 
const int INF = 1000000000;
 
struct Edge { int to; int cost; };
 
void dijkstra(int n, int t, const vector<vector<int>>& graph, vector<int>& dist) {
    dist.assign(n, INF);
    dist[t] = 0;
    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
    pq.push({0, t});
    while(!pq.empty()){
        auto [d, u] = pq.top();
        pq.pop();
        if(d != dist[u]) continue;
        for (int v = 0; v < n; v++){
            int w = graph[u][v];
            if(w > 0){
                if(dist[v] > d + w){
                    dist[v] = d + w;
                    pq.push({dist[v], v});
                }
            }
        }
    }
}
 
bool gauss(vector<vector<double>> A, vector<double> b, vector<double>& sol) {
    int n = A.size();
    sol.assign(n, 0);
    const double EPS = 1e-12;
    for (int i = 0; i < n; i++){
        int pivot = i;
        for (int r = i; r < n; r++){
            if (fabs(A[r][i]) > fabs(A[pivot][i]))
                pivot = r;
        }
        if (fabs(A[pivot][i]) < EPS) return false;
        swap(A[i], A[pivot]);
        swap(b[i], b[pivot]);
 
        double div = A[i][i];
        for (int j = i; j < n; j++) A[i][j] /= div;
        b[i] /= div;
 
        for (int r = 0; r < n; r++){
            if(r == i) continue;
            double factor = A[r][i];
            for (int j = i; j < n; j++)
                A[r][j] -= factor * A[i][j];
            b[r] -= factor * b[i];
        }
    }
    sol = b;
    return true;
}
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    while(true) {
        int n, s, t;
        cin >> n >> s >> t;
        if(n==0) break;
        s--; t--;
 
        vector<int> hasSign(n, 0);
        for (int i = 0; i < n; i++) cin >> hasSign[i];
 
        vector<vector<int>> graph(n, vector<int>(n, 0));
        for (int i = 0; i < n; i++){
            for (int j = 0; j < n; j++) cin >> graph[i][j];
        }
 
        vector<int> D;
        dijkstra(n, t, graph, D);
 
        if(D[s] >= INF) {
            cout << "impossible" << endl;
            continue;
        }
 
        vector<vector<Edge>> allowed(n);
        for (int u = 0; u < n; u++){
            if(u == t) continue;
            if(hasSign[u] == 1) {
                if(D[u] >= INF) continue;
                for (int v = 0; v < n; v++){
                    if(graph[u][v] > 0){
                        if(D[v] >= INF) continue;
                        if(D[u] == graph[u][v] + D[v])
                            allowed[u].push_back({v, graph[u][v]});
                    }
                }
            } else {
                for (int v = 0; v < n; v++){
                    if(graph[u][v] > 0)
                        allowed[u].push_back({v, graph[u][v]});
                }
            }
        }
 
        vector<vector<int>> rev(n);
        for (int u = 0; u < n; u++){
            for(auto &edge: allowed[u]){
                int v = edge.to;
                rev[v].push_back(u);
            }
        }
        vector<bool> inR(n, false);
        {
            stack<int> st;
            st.push(t);
            inR[t] = true;
            while(!st.empty()){
                int cur = st.top();
                st.pop();
                for (int u: rev[cur]){
                    if(!inR[u]){
                        inR[u] = true;
                        st.push(u);
                    }
                }
            }
        }
 
        vector<bool> inA = inR;
        queue<int> que;
        for (int u = 0; u < n; u++){
            if(u == t) continue;
            if(inA[u]){
                for(auto &edge: allowed[u]){
                    int v = edge.to;
                    if(!inA[v]){
                        que.push(u);
                        break;
                    }
                }
            }
        }
        while(!que.empty()){
            int u = que.front();
            que.pop();
            if(!inA[u]) continue;
            inA[u] = false;
            for (int w: rev[u]){
                if(w == t) continue;
                if(inA[w]){
                    for(auto &edge: allowed[w]){
                        int v = edge.to;
                        if(!inA[v]){
                            que.push(w);
                            break;
                        }
                    }
                }
            }
        }
 
        if(!inA[s]){
            cout << "impossible" << endl;
            continue;
        }
 
        vector<int> idxMapping(n, -1);
        vector<int> inSet;
        for (int u = 0; u < n; u++){
            if(inA[u]){
                idxMapping[u] = inSet.size();
                inSet.push_back(u);
            }
        }
        int m = inSet.size();
        vector<vector<double>> Aeq(m, vector<double>(m, 0.0));
        vector<double> Beq(m, 0.0);
 
        for (int i = 0; i < m; i++){
            int u = inSet[i];
            if(u == t) {
                Aeq[i][i] = 1.0;
                Beq[i] = 0.0;
                continue;
            }
            int deg = allowed[u].size();
            Aeq[i][i] = 1.0;
            double sumCost = 0.0;
            for (auto &edge: allowed[u]){
                int v = edge.to;
                double prob = 1.0 / deg;
                Aeq[i][idxMapping[v]] -= prob;
                sumCost += prob * edge.cost;
            }
            Beq[i] = sumCost;
        }
 
        vector<double> sol;
        bool ok = gauss(Aeq, Beq, sol);
        if(!ok)
            cout << "impossible" << endl;
        else
            cout << fixed << setprecision(10) << sol[idxMapping[s]] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4044
final_rank: 11

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
 */

bool eq(double A, double B) {
    return abs(A-B) < 1e-8;
}

template <class T> struct Matrix {
    int h, w;
    vector<vector<T>> val;
    T det;
    Matrix() {}
    Matrix(int n) : h(n), w(n), val(vector<vector<T>>(n, vector<T>(n))) {}
    Matrix(int n, int m)
        : h(n), w(m), val(vector<vector<T>>(n, vector<T>(m))) {}
    vector<T> &operator[](const int i) {
        return val[i];
    }
    Matrix &operator+=(const Matrix &m) {
        assert(h == m.h and w == m.w);
        rep(i, 0, h) rep(j, 0, w) val[i][j] += m.val[i][j];
        return *this;
    }
    Matrix &operator-=(const Matrix &m) {
        assert(h == m.h and w == m.w);
        rep(i, 0, h) rep(j, 0, w) val[i][j] -= m.val[i][j];
        return *this;
    }
    Matrix &operator*=(const Matrix &m) {
        assert(w == m.h);
        Matrix<T> res(h, m.w);
        rep(i, 0, h) rep(j, 0, m.w) rep(k, 0, w) res.val[i][j] +=
            val[i][k] * m.val[k][j];
        *this = res;
        return *this;
    }
    Matrix operator+(const Matrix &m) const {
        return Matrix(*this) += m;
    }
    Matrix operator-(const Matrix &m) const {
        return Matrix(*this) -= m;
    }
    Matrix operator*(const Matrix &m) const {
        return Matrix(*this) *= m;
    }
    Matrix pow(ll k) {
        Matrix<T> res(h, h), c = *this;
        rep(i, 0, h) res.val[i][i] = 1;
        while (k) {
            if (k & 1)
                res *= c;
            c *= c;
            k >>= 1;
        }
        return res;
    }
    vector<int> gauss(int c = -1) {
        det = 1;
        if (val.empty())
            return {};
        if (c == -1)
            c = w;
        int cur = 0;
        vector<int> res;
        rep(i, 0, c) {
            if (cur == h)
                break;
            rep(j, cur, h) if (!eq(val[j][i], 0.0)) {
                swap(val[cur], val[j]);
                if (cur != j)
                    det *= -1;
                break;
            }
            det *= val[cur][i];
            if (eq(val[cur][i], 0.0))
                continue;
            rep(j, 0, h) if (j != cur) {
                T z = val[j][i] / val[cur][i];
                rep(k, i, w) val[j][k] -= val[cur][k] * z;
            }
            res.push_back(i);
            cur++;
        }
        return res;
    }
    Matrix inv() {
        assert(h == w);
        Matrix base(h, h * 2), res(h, h);
        rep(i, 0, h) rep(j, 0, h) base[i][j] = val[i][j];
        rep(i, 0, h) base[i][h + i] = 1;
        base.gauss(h);
        det = base.det;
        rep(i, 0, h) rep(j, 0, h) res[i][j] = base[i][h + j] / base[i][i];
        return res;
    }
    bool operator==(const Matrix &m) {
        assert(h == m.h and w == m.w);
        rep(i, 0, h) rep(j, 0, w) if (val[i][j] != m.val[i][j]) return false;
        return true;
    }
    bool operator!=(const Matrix &m) {
        assert(h == m.h and w == m.w);
        rep(i, 0, h) rep(j, 0, w) if (val[i][j] == m.val[i][j]) return false;
        return true;
    }
    friend istream &operator>>(istream &is, Matrix &m) {
        rep(i, 0, m.h) rep(j, 0, m.w) is >> m[i][j];
        return is;
    }
    friend ostream &operator<<(ostream &os, Matrix &m) {
        rep(i, 0, m.h) {
            rep(j, 0, m.w) os << m[i][j]
                              << (j == m.w - 1 and i != m.h - 1 ? '\n' : ' ');
        }
        return os;
    }
};

/**
 * @brief Matrix
 */

template<typename T>pair<vector<T>,Matrix<T>> LinearEquation(Matrix<T> a,vector<T> b){
   int h=a.h,w=a.w;
   rep(i,0,h)a[i].push_back(b[i]);
   a.w++;
   vector<int> idx=a.gauss(w);
   rep(i,idx.size(),h)if(!eq(a[i][w],0.0))return {{},{}};
   vector<T> res(w);
   rep(i,0,idx.size())res[idx[i]]=a[i][w]/a[i][idx[i]];
   Matrix<T> d(w,h+w);
   rep(i,0,h)rep(j,0,w)d[j][i]=a[i][j];
   rep(i,0,w)d[i][h+i]=1;
   int r=d.gauss(h).size();
   Matrix<T> basis(w-r,w);
   rep(i,r,w)basis[i-r]={d[i].begin()+h,d[i].end()};
   return {res,basis};
}

/**
 * @brief Linear Equation
 */

int main() {
while(1) {
    int N, S, T;
    cin >> N >> S >> T;
    if (N == 0) return 0;
    S--, T--;
    vector<int> X(N);
    rep(i,0,N) cin >> X[i];
    vector<vector<int>> A(N,vector<int>(N));
    rep(i,0,N) rep(j,0,N) cin >> A[i][j];
    auto D = A;
    rep(i,0,N) rep(j,0,N) if (D[i][j] == 0) D[i][j] = inf;
    rep(i,0,N) D[i][i] = 0;
    rep(k,0,N) {
        rep(i,0,N) {
            rep(j,0,N) chmin(D[i][j], D[i][k]+D[k][j]);
        }
    }
    if (D[S][T] == inf) {
        cout << "impossible" << endl;
        continue;
    }
    Matrix<double> Mat(N);
    vector<double> Vec(N);
    rep(i,0,N) {
        if (i == T) {
            Mat[i][i] = 1.0;
            Vec[i] = 0.0;
            continue;
        }
        bool check = false;
        vector<int> To;
        rep(j,0,N) {
            if (A[i][j] == 0) continue;
            if (X[i] == 1 && D[i][T] != A[i][j] + D[j][T]) continue;
            if (i == j) check = true;
            else To.push_back(j);
        }
        int K = To.size();
        if (check) {
            Vec[i] = A[i][i];
            Mat[i][i] = (double)K;
            for (int j : To) {
                Mat[i][j] = -1.0;
                Vec[i] += (double)A[i][j];
            }
        }
        else {
            Vec[i] = 0.0;
            Mat[i][i] = (double)K;
            for (int j : To) {
                Mat[i][j] = -1.0;
                Vec[i] += (double)A[i][j];
            }
        }
    }
    auto ANS = LinearEquation(Mat, Vec);
    if (ANS.first.empty()) {
        cout << "impossible" << endl;
    }
    else {
        printf("%.12f\n", ANS.first[S]);
    }
}
}
accuracy: 1
time_ms: 50
memory_kb: 3824
final_rank: 14

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"

// basic settings
long double EPS = 1e-10;  // to be set appropriately

// matrix
template<class T> struct Matrix {
    // inner value
    vector<vector<T>> val;
    
    // constructors
    Matrix(int H, int W, T x = 0) : val(H, vector<T>(W, x)) {}
    Matrix(const Matrix &mat) : val(mat.val) {}
    void init(int H, int W, T x = 0) {
        val.assign(H, vector<T>(W, x));
    }
    void resize(int H, int W) {
        val.resize(H);
        for (int i = 0; i < H; ++i) val[i].resize(W);
    }
    
    // getter and debugger
    constexpr int height() const { return (int)val.size(); }
    constexpr int width() const { return (int)val[0].size(); }
    vector<T>& operator [] (int i) { return val[i]; }
    constexpr vector<T>& operator [] (int i) const { return val[i]; }
    friend constexpr ostream& operator << (ostream &os, const Matrix<T> &mat) {
        os << endl;
        for (int i = 0; i < mat.height(); ++i) {
            for (int j = 0; j < mat.width(); ++j) {
                if (j) os << ", ";
                os << mat[i][j];
            }
            os << endl;
        }
        return os;
    }
    
    // comparison operators
    constexpr bool operator == (const Matrix &r) const {
        return this->val == r.val;
    }
    constexpr bool operator != (const Matrix &r) const {
        return this->val != r.val;
    }
    
    // arithmetic operators
    constexpr Matrix& operator += (const Matrix &r) {
        assert(height() == r.height());
        assert(width() == r.width());
        for (int i = 0; i < height(); ++i) {
            for (int j = 0; j < width(); ++j) {
                val[i][j] += r[i][j];
            }
        }
        return *this;
    }
    constexpr Matrix& operator -= (const Matrix &r) {
        assert(height() == r.height());
        assert(width() == r.width());
        for (int i = 0; i < height(); ++i) {
            for (int j = 0; j < width(); ++j) {
                val[i][j] -= r[i][j];
            }
        }
        return *this;
    }
    constexpr Matrix& operator *= (T v) {
        for (int i = 0; i < height(); ++i)
            for (int j = 0; j < width(); ++j)
                val[i][j] *= v;
        return *this;
    }
    constexpr Matrix& operator *= (const Matrix &r) {
        assert(width() == r.height());
        Matrix<T> res(height(), r.width());
        for (int i = 0; i < height(); ++i)
            for (int j = 0; j < r.width(); ++j)
                for (int k = 0; k < width(); ++k)
                    res[i][j] += val[i][k] * r[k][j];
        return (*this) = res;
    }
    constexpr Matrix operator + () const { return Matrix(*this); }
    constexpr Matrix operator - () const { return Matrix(*this) *= T(-1); }
    constexpr Matrix operator + (const Matrix &r) const { return Matrix(*this) += r; }
    constexpr Matrix operator - (const Matrix &r) const { return Matrix(*this) -= r; }
    constexpr Matrix operator * (T v) const { return Matrix(*this) *= v; }
    constexpr Matrix operator * (const Matrix &r) const { return Matrix(*this) *= r; }
    
    // pow
    constexpr Matrix pow(long long n) const {
        assert(height() == width());
        Matrix<T> res(height(), width()),  mul(*this);
        while (n > 0) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    friend constexpr Matrix<T> pow(const Matrix<T> &mat, long long n) {
        return mat.pow(n);
    }
    
    // gauss-jordan
    constexpr int gauss_jordan(bool is_extended = false) {
        int rank = 0;
        for (int col = 0; col < width(); ++col) {
            if (is_extended && col == width() - 1) break;
            int pivot = -1;
            T max_v = EPS;
            for (int row = rank; row < height(); ++row) {
                if (abs(val[row][col]) > max_v) {
                    max_v = abs(val[row][col]);
                    pivot = row;
                }
            }
            if (pivot == -1) continue;
            swap(val[pivot], val[rank]);
            auto fac = val[rank][col];
            for (int col2 = 0; col2 < width(); ++col2) val[rank][col2] /= fac;
            for (int row = 0; row < height(); ++row) {
                if (row != rank && abs(val[row][col]) > EPS) {
                    auto fac = val[row][col];
                    for (int col2 = 0; col2 < width(); ++col2) {
                        val[row][col2] -= val[rank][col2] * fac;
                    }
                }
            }
            ++rank;
        }
        return rank;
    }
    friend constexpr int gauss_jordan(Matrix<T> &mat, bool is_extended = false) {
        return mat.gauss_jordan(is_extended);
    }
    friend constexpr vector<T> linear_equation(const Matrix<T> &mat, const vector<T> &b) {
        // extended
        Matrix<T> A(mat.height(), mat.width() + 1);
        for (int i = 0; i < mat.height(); ++i) {
            for (int j = 0; j < mat.width(); ++j) A[i][j] = mat.val[i][j];
            A[i].back() = b[i];
        }
        int rank = A.gauss_jordan(true);
        
        // check if it has no solution
        vector<T> res;
        for (int row = rank; row < mat.height(); ++row)
            if (abs(A[row].back()) > EPS)
                return res;

        // answer
        res.assign(mat.width(), 0);
        for (int i = 0; i < rank; ++i) res[i] = A[i].back();
        return res;
    }
};

f64 solve(int n, int s, int t) {
    s--, t--;
    vector<int> q = in(n);
    vector<vector<int>> a = in(n, n);
    constexpr int INF = 1e9;
    vector d(n, vector(n, int(INF)));
    for(int i : rep(n)) for(int j : rep(n)) if(a[i][j] != 0) d[i][j] = a[i][j];
    for(int i : rep(n)) d[i][i] = 0;
    for(int k : rep(n)) for(int i : rep(n)) for(int j : rep(n)) chmin(d[i][j], d[i][k] + d[k][j]);
    if(d[s][t] == INF) return -100;

    Matrix<f64> A(n, n, 0.0);
    vector<f64> b(n, 0.0);
    A[t][t] = 1;
    b[t] = 0;
    for(int v : rep(n)) if(v != t) {
        vector<int> tos;
        if(q[v] == 1) {
            for(int to : rep(n)) if(a[v][to] != 0) {
                if(a[v][to] + d[to][t] == d[v][t]) tos.push_back(to);
            }
        } else {
            for(int to : rep(n)) if(a[v][to] != 0) tos.push_back(to);
        }

        for(int to : tos) {
            A[v][to] -= 1;
            b[v] += a[v][to];
        }
        A[v][v] += tos.size();
    }

    auto x = linear_equation(A, b);
    return x[s];
}

int main() {
    while(true) {
        int n = in(), s = in(), t = in();
        if(n == 0) return 0;
        f64 ans = solve(n, s, t);
        if(ans < -50) {
            print("impossible");
        } else {
            printer::precision(20);
            print(ans);
        }
    }
}
accuracy: 1
time_ms: 30
memory_kb: 3868
final_rank: 12

code_snippet: //
// 実数行列 (行列累乗と、掃き出し法)
//
// verified:
//   AOJ 2171 Strange Couple
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2171
//
//   AOJ 1328 Find the Outlier
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1328
//


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


// basic settings
long double EPS = 1e-10;  // to be set appropriately

// matrix
template<class T> struct Matrix {
    // inner value
    vector<vector<T>> val;
    
    // constructors
    Matrix(int H, int W, T x = 0) : val(H, vector<T>(W, x)) {}
    Matrix(const Matrix &mat) : val(mat.val) {}
    void init(int H, int W, T x = 0) {
        val.assign(H, vector<T>(W, x));
    }
    void resize(int H, int W) {
        val.resize(H);
        for (int i = 0; i < H; ++i) val[i].resize(W);
    }
    
    // getter and debugger
    constexpr int height() const { return (int)val.size(); }
    constexpr int width() const { return (int)val[0].size(); }
    vector<T>& operator [] (int i) { return val[i]; }
    constexpr vector<T>& operator [] (int i) const { return val[i]; }
    friend constexpr ostream& operator << (ostream &os, const Matrix<T> &mat) {
        os << endl;
        for (int i = 0; i < mat.height(); ++i) {
            for (int j = 0; j < mat.width(); ++j) {
                if (j) os << ", ";
                os << mat.val[i][j];
            }
            os << endl;
        }
        return os;
    }
    
    // comparison operators
    constexpr bool operator == (const Matrix &r) const {
        return this->val == r.val;
    }
    constexpr bool operator != (const Matrix &r) const {
        return this->val != r.val;
    }
    
    // arithmetic operators
    constexpr Matrix& operator += (const Matrix &r) {
        assert(height() == r.height());
        assert(width() == r.width());
        for (int i = 0; i < height(); ++i) {
            for (int j = 0; j < width(); ++j) {
                val[i][j] += r[i][j];
            }
        }
        return *this;
    }
    constexpr Matrix& operator -= (const Matrix &r) {
        assert(height() == r.height());
        assert(width() == r.width());
        for (int i = 0; i < height(); ++i) {
            for (int j = 0; j < width(); ++j) {
                val[i][j] -= r[i][j];
            }
        }
        return *this;
    }
    constexpr Matrix& operator *= (T v) {
        for (int i = 0; i < height(); ++i)
            for (int j = 0; j < width(); ++j)
                val[i][j] *= v;
        return *this;
    }
    constexpr Matrix& operator *= (const Matrix &r) {
        assert(width() == r.height());
        Matrix<T> res(height(), r.width());
        for (int i = 0; i < height(); ++i)
            for (int j = 0; j < r.width(); ++j)
                for (int k = 0; k < width(); ++k)
                    res[i][j] += val[i][k] * r[k][j];
        return (*this) = res;
    }
    constexpr Matrix operator + () const { return Matrix(*this); }
    constexpr Matrix operator - () const { return Matrix(*this) *= T(-1); }
    constexpr Matrix operator + (const Matrix &r) const { return Matrix(*this) += r; }
    constexpr Matrix operator - (const Matrix &r) const { return Matrix(*this) -= r; }
    constexpr Matrix operator * (T v) const { return Matrix(*this) *= v; }
    constexpr Matrix operator * (const Matrix &r) const { return Matrix(*this) *= r; }
    
    // pow
    constexpr Matrix pow(long long n) const {
        assert(height() == width());
        Matrix<T> res(height(), width()),  mul(*this);
        while (n > 0) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    friend constexpr Matrix<T> pow(const Matrix<T> &mat, long long n) {
        return mat.pow(n);
    }
    
    // gauss-jordan
    constexpr int find_pivot(int cur_rank, int col) const {
        int pivot = -1;
        T max_v = EPS;
        for (int row = cur_rank; row < height(); ++row) {
            if (abs(val[row][col]) > max_v) {
                max_v = abs(val[row][col]);
                pivot = row;
            }
        }
        return pivot;
    }
    constexpr void sweep(int cur_rank, int col, int pivot) {
        swap(val[pivot], val[cur_rank]);
        auto fac = val[cur_rank][col];
        for (int col2 = 0; col2 < width(); ++col2) {
            val[cur_rank][col2] /= fac;
        }
        for (int row = 0; row < height(); ++row) {
            if (row != cur_rank && abs(val[row][col]) > EPS) {
                auto fac = val[row][col];
                for (int col2 = 0; col2 < width(); ++col2) {
                    val[row][col2] -= val[cur_rank][col2] * fac;
                }
            }
        }
    }
    constexpr int gauss_jordan(int not_sweep_width = 0) {
        int rank = 0;
        for (int col = 0; col < width(); ++col) {
            if (col == width() - not_sweep_width) break;
            int pivot = find_pivot(rank, col);
            if (pivot == -1) continue;
            sweep(rank++, col, pivot);
        }
        return rank;
    }
    friend constexpr int gauss_jordan(Matrix<T> &mat, int not_sweep_width = 0) {
        return mat.gauss_jordan(not_sweep_width);
    }
    friend constexpr vector<T> linear_equation(const Matrix<T> &mat, const vector<T> &b) {
        // extend
        Matrix<T> A(mat.height(), mat.width() + 1);
        for (int i = 0; i < mat.height(); ++i) {
            for (int j = 0; j < mat.width(); ++j) A[i][j] = mat.val[i][j];
            A[i].back() = b[i];
        }
        int rank = A.gauss_jordan(1);
        
        // check if it has no solution
        vector<T> res;
        for (int row = rank; row < mat.height(); ++row)
            if (abs(A[row].back()) > EPS)
                return res;

        // answer
        res.assign(mat.width(), 0);
        for (int i = 0; i < rank; ++i) res[i] = A[i].back();
        return res;
    }
};



/*/////////////////////////////*/
// Examples
/*/////////////////////////////*/

void AOJ_2171() {
    int N, s, t;
    while (cin >> N >> s >> t, N) {
        --s, --t;
        vector<int> q(N);
        vector<vector<int>> a(N, vector<int>(N));
        for (int i = 0; i < N; ++i) cin >> q[i];
        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cin >> a[i][j];

        // Dijkstra
        const int INF = 1<<29;
        vector<int> dist(N, INF);
        vector<bool> seen(N, 0);
        dist[t] = 0;
        for (int iter = 0; iter < N; ++iter) {
            int curd = INF;
            int v = -1;
            for (int i = 0; i < N; ++i) {
                if (seen[i]) continue;
                if (curd > dist[i]) {
                    curd = dist[i];
                    v = i;
                }
            }
            if (v == -1) break;
            for (int w = 0; w < N; ++w) {
                if (w == v) continue;
                if (a[v][w] == 0) continue;
                dist[w] = min(dist[w], curd + a[v][w]);
            }
            seen[v] = true;
        }
        if (dist[s] >= INF) {
            cout << "impossible" << endl;
            return;
        }

        // 連立一次方程式を作る
        Matrix<double> A(N, N, 0);
        vector<double> b(N, 0);
        for (int v = 0; v < N; ++v) {
            if (v == t) {
                A[v][v] = 1;
                b[v] = 0;
            }
            else {
                vector<int> neigbor;
                for (int w = 0; w < N; ++w) {
                    if (a[v][w] == 0) continue;
                    if (q[v] == 1 && dist[w] + a[v][w] != dist[v]) continue;
                    neigbor.push_back(w);
                }
                int K = neigbor.size();
                for (auto w : neigbor) {
                    A[v][w] -= 1;
                    b[v] += a[v][w];
                }
                A[v][v] += K;
            }
        }
          
        // 解く
        auto res = linear_equation(A, b);
        if (res.empty()) cout << "impossible" << endl;
        else cout << fixed << setprecision(15) << res[s] << endl;
    }
}

void AOJ_1328() {
    using D = long double;
    EPS = 1e-5;  // set EPS
    
    auto dpow = [&](D a, int n) -> D {
        D res = 1.0;
        for (int i = 0; i < n; ++i) res *= a;
        return res;
    };
    auto func = [&](const vector<D> &coef, int i) -> D {
        D res = 0.0;
        for (int p = 0; p < (int)coef.size(); ++p)
            res += coef[p] * pow(i, p);
        return res;
    };
    
    int d;
    while (cin >> d, d) {
        vector<D> v(d + 3);
        for (int i = 0; i < d + 3; ++i) cin >> v[i];

        bool finish = false;
        int res = 0;
        for (int i = 0; i < d + 3 && !finish; ++i) {
            for (int j = i + 1; j < d + 3 && !finish; ++j) {
                Matrix<D> A(d + 1, d + 1);
                vector<D> b(d + 1);
                for (int k = 0, iter = 0; k < d+3; ++k) {
                    if (k == i || k == j) continue;
                    for (int p = 0; p < d + 1; ++p) {
                        A[iter][p] = pow(k, p);
                        b[iter] = v[k];
                    }
                    ++iter;
                }
                vector<D> ans = linear_equation(A, b);
                if (ans.empty()) continue;
                D vi = func(ans, i), vj = func(ans, j);
                int num = 0;
                if (fabs(vi - v[i]) > EPS) res = i, ++num;
                if (fabs(vj - v[j]) > EPS) res = j, ++num;
                if (num == 1) goto end;
            }
        }
        end:
        cout << res << endl;
    }
}


int main() {
    AOJ_2171();
    //AOJ_1328();
}
accuracy: 1
time_ms: 20
memory_kb: 3764
final_rank: 6

code_snippet: //
// 実数行列 (行列累乗と、掃き出し法)
//
// verified:
//   AOJ 2171 Strange Couple
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2171
//
//   AOJ 1328 Find the Outlier
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1328
//


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


// basic settings
long double EPS = 1e-10;  // to be set appropriately

// matrix
template<class T> struct Matrix {
    // inner value
    vector<vector<T>> val;
    
    // constructors
    Matrix(int H, int W, T x = 0) : val(H, vector<T>(W, x)) {}
    Matrix(const Matrix &mat) : val(mat.val) {}
    void init(int H, int W, T x = 0) {
        val.assign(H, vector<T>(W, x));
    }
    void resize(int H, int W) {
        val.resize(H);
        for (int i = 0; i < H; ++i) val[i].resize(W);
    }
    
    // getter and debugger
    constexpr int height() const { return (int)val.size(); }
    constexpr int width() const { return (int)val[0].size(); }
    vector<T>& operator [] (int i) { return val[i]; }
    constexpr vector<T>& operator [] (int i) const { return val[i]; }
    friend constexpr ostream& operator << (ostream &os, const Matrix<T> &mat) {
        os << endl;
        for (int i = 0; i < mat.height(); ++i) {
            for (int j = 0; j < mat.width(); ++j) {
                if (j) os << ", ";
                os << mat[i][j];
            }
            os << endl;
        }
        return os;
    }
    
    // comparison operators
    constexpr bool operator == (const Matrix &r) const {
        return this->val == r.val;
    }
    constexpr bool operator != (const Matrix &r) const {
        return this->val != r.val;
    }
    
    // arithmetic operators
    constexpr Matrix& operator += (const Matrix &r) {
        assert(height() == r.height());
        assert(width() == r.width());
        for (int i = 0; i < height(); ++i) {
            for (int j = 0; j < width(); ++j) {
                val[i][j] += r[i][j];
            }
        }
        return *this;
    }
    constexpr Matrix& operator -= (const Matrix &r) {
        assert(height() == r.height());
        assert(width() == r.width());
        for (int i = 0; i < height(); ++i) {
            for (int j = 0; j < width(); ++j) {
                val[i][j] -= r[i][j];
            }
        }
        return *this;
    }
    constexpr Matrix& operator *= (T v) {
        for (int i = 0; i < height(); ++i)
            for (int j = 0; j < width(); ++j)
                val[i][j] *= v;
        return *this;
    }
    constexpr Matrix& operator *= (const Matrix &r) {
        assert(width() == r.height());
        Matrix<T> res(height(), r.width());
        for (int i = 0; i < height(); ++i)
            for (int j = 0; j < r.width(); ++j)
                for (int k = 0; k < width(); ++k)
                    res[i][j] += val[i][k] * r[k][j];
        return (*this) = res;
    }
    constexpr Matrix operator + () const { return Matrix(*this); }
    constexpr Matrix operator - () const { return Matrix(*this) *= T(-1); }
    constexpr Matrix operator + (const Matrix &r) const { return Matrix(*this) += r; }
    constexpr Matrix operator - (const Matrix &r) const { return Matrix(*this) -= r; }
    constexpr Matrix operator * (T v) const { return Matrix(*this) *= v; }
    constexpr Matrix operator * (const Matrix &r) const { return Matrix(*this) *= r; }
    
    // pow
    constexpr Matrix pow(long long n) const {
        assert(height() == width());
        Matrix<T> res(height(), width()),  mul(*this);
        while (n > 0) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    friend constexpr Matrix<T> pow(const Matrix<T> &mat, long long n) {
        return mat.pow(n);
    }
    
    // gauss-jordan
    constexpr int gauss_jordan(bool is_extended = false) {
        int rank = 0;
        for (int col = 0; col < width(); ++col) {
            if (is_extended && col == width() - 1) break;
            int pivot = -1;
            T max_v = EPS;
            for (int row = rank; row < height(); ++row) {
                if (abs(val[row][col]) > max_v) {
                    max_v = abs(val[row][col]);
                    pivot = row;
                }
            }
            if (pivot == -1) continue;
            swap(val[pivot], val[rank]);
            auto fac = val[rank][col];
            for (int col2 = 0; col2 < width(); ++col2) val[rank][col2] /= fac;
            for (int row = 0; row < height(); ++row) {
                if (row != rank && abs(val[row][col]) > EPS) {
                    auto fac = val[row][col];
                    for (int col2 = 0; col2 < width(); ++col2) {
                        val[row][col2] -= val[rank][col2] * fac;
                    }
                }
            }
            ++rank;
        }
        return rank;
    }
    friend constexpr int gauss_jordan(Matrix<T> &mat, bool is_extended = false) {
        return mat.gauss_jordan(is_extended);
    }
    friend constexpr vector<T> linear_equation(const Matrix<T> &mat, const vector<T> &b) {
        // extended
        Matrix<T> A(mat.height(), mat.width() + 1);
        for (int i = 0; i < mat.height(); ++i) {
            for (int j = 0; j < mat.width(); ++j) A[i][j] = mat.val[i][j];
            A[i].back() = b[i];
        }
        int rank = A.gauss_jordan(true);
        
        // check if it has no solution
        vector<T> res;
        for (int row = rank; row < mat.height(); ++row)
            if (abs(A[row].back()) > EPS)
                return res;

        // answer
        res.assign(mat.width(), 0);
        for (int i = 0; i < rank; ++i) res[i] = A[i].back();
        return res;
    }
};



/*/////////////////////////////*/
// Examples
/*/////////////////////////////*/

void AOJ_2171() {
    int N, s, t;
    while (cin >> N >> s >> t, N) {
        --s, --t;
        vector<int> q(N);
        vector<vector<int>> a(N, vector<int>(N));
        for (int i = 0; i < N; ++i) cin >> q[i];
        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cin >> a[i][j];

        // Dijkstra
        const int INF = 1<<29;
        vector<int> dist(N, INF);
        vector<bool> seen(N, 0);
        dist[t] = 0;
        for (int iter = 0; iter < N; ++iter) {
            int curd = INF;
            int v = -1;
            for (int i = 0; i < N; ++i) {
                if (seen[i]) continue;
                if (curd > dist[i]) {
                    curd = dist[i];
                    v = i;
                }
            }
            if (v == -1) break;
            for (int w = 0; w < N; ++w) {
                if (w == v) continue;
                if (a[v][w] == 0) continue;
                dist[w] = min(dist[w], curd + a[v][w]);
            }
            seen[v] = true;
        }
        if (dist[s] >= INF) {
            cout << "impossible" << endl;
            return;
        }

        // 連立一次方程式を作る
        Matrix<double> A(N, N, 0);
        vector<double> b(N, 0);
        for (int v = 0; v < N; ++v) {
            if (v == t) {
                A[v][v] = 1;
                b[v] = 0;
            }
            else {
                vector<int> neigbor;
                for (int w = 0; w < N; ++w) {
                    if (a[v][w] == 0) continue;
                    if (q[v] == 1 && dist[w] + a[v][w] != dist[v]) continue;
                    neigbor.push_back(w);
                }
                int K = neigbor.size();
                for (auto w : neigbor) {
                    A[v][w] -= 1;
                    b[v] += a[v][w];
                }
                A[v][v] += K;
            }
        }
        
        // 解く
        auto res = linear_equation(A, b);
        if (res.empty()) cout << "impossible" << endl;
        else cout << fixed << setprecision(15) << res[s] << endl;
    }
}


int main() {
    AOJ_2171();
}
accuracy: 1
time_ms: 20
memory_kb: 3592
final_rank: 2

code_snippet: //
// 実数行列 (行列累乗と、掃き出し法)
//
// verified:
//   AOJ 2171 Strange Couple
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2171
//


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


// basic settings
long double EPS = 1e-10;  // to be set appropriately

template<class T> struct Matrix {
    // inner value
    vector<vector<T>> val;
    
    // constructors
    Matrix(int n, int m, T x = 0) : val(n, vector<T>(m, x)) {}
    void init(int n, int m, T x = 0) {
        val.assign(n, vector<T>(m, x));
    }
    
    // getter
    size_t size() const { return val.size(); }
    vector<T>& operator [] (int i) { return val[i]; }
    constexpr vector<T>& operator [] (int i) const { return val[i]; }
};

template<class T> ostream& operator << (ostream& s, Matrix<T> A) {
    s << endl;
    for (int i = 0; i < A.size(); ++i) {
        for (int j = 0; j < A[i].size(); ++j) {
            s << A[i][j] << ", ";
        }
        s << endl;
    }
    return s;
}

template<class T> Matrix<T> operator * (const Matrix<T> &A, const Matrix<T> &B) {
    Matrix<T> R(A.size(), B[0].size());
    for (int i = 0; i < A.size(); ++i)
        for (int j = 0; j < B[0].size(); ++j)
            for (int k = 0; k < B.size(); ++k)
                R[i][j] += A[i][k] * B[k][j];
    return R;
}

template<class T> Matrix<T> pow(Matrix<T> A, long long n) {
    Matrix<T> R(A.size(), A.size());
    for (int i = 0; i < A.size(); ++i) R[i][i] = 1;
    while (n > 0) {
        if (n & 1) R = R * A;
        A = A * A;
        n >>= 1;
    }
    return R;
}

template<class T> int GaussJordan(Matrix<T> &A, bool is_extended = false) {
    int m = A.size(), n = A[0].size();
    int rank = 0;
    for (int col = 0; col < n; ++col) {
        if (is_extended && col == n-1) break;
        int pivot = -1;
        T ma = EPS;
        for (int row = rank; row < m; ++row) {
            if (abs(A[row][col]) > ma) {
                ma = abs(A[row][col]);
                pivot = row;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        auto fac = A[rank][col];
        for (int col2 = 0; col2 < n; ++col2) A[rank][col2] /= fac;
        for (int row = 0; row < m; ++row) {
            if (row != rank && abs(A[row][col]) > EPS) {
                auto fac = A[row][col];
                for (int col2 = 0; col2 < n; ++col2) {
                    A[row][col2] -= A[rank][col2] * fac;
                }
            }
        }
        ++rank;
    }
    return rank;
}

template<class T> vector<T> linear_equation(Matrix<T> A, vector<T> b) {
    // extended
    int m = A.size(), n = A[0].size();
    Matrix<T> M(m, n + 1);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    
    // check if it has no solution
    vector<T> res;
    for (int row = rank; row < m; ++row) if (abs(M[row][n]) > EPS) return res;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return res;
}



/*/////////////////////////////*/
// Examples
/*/////////////////////////////*/

void AOJ_2171() {
    int N, s, t;
    while (cin >> N >> s >> t, N) {
        --s, --t;
        vector<int> q(N);
        vector<vector<int>> a(N, vector<int>(N));
        for (int i = 0; i < N; ++i) cin >> q[i];
        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cin >> a[i][j];

        // Dijkstra
        const int INF = 1<<29;
        vector<int> dist(N, INF);
        vector<bool> seen(N, 0);
        dist[t] = 0;
        for (int iter = 0; iter < N; ++iter) {
            int curd = INF;
            int v = -1;
            for (int i = 0; i < N; ++i) {
                if (seen[i]) continue;
                if (curd > dist[i]) {
                    curd = dist[i];
                    v = i;
                }
            }
            if (v == -1) break;
            for (int w = 0; w < N; ++w) {
                if (w == v) continue;
                if (a[v][w] == 0) continue;
                dist[w] = min(dist[w], curd + a[v][w]);
            }
            seen[v] = true;
        }
        if (dist[s] >= INF) {
            cout << "impossible" << endl;
            return;
        }

        // 連立一次方程式
        Matrix<double> A(N, N, 0);
        vector<double> b(N, 0);
        for (int v = 0; v < N; ++v) {
            if (v == t) {
                A[v][v] = 1;
                b[v] = 0;
            }
            else {
                vector<int> neigbor;
                for (int w = 0; w < N; ++w) {
                    if (a[v][w] == 0) continue;
                    if (q[v] == 1 && dist[w] + a[v][w] != dist[v]) continue;
                    neigbor.push_back(w);
                }
                int K = neigbor.size();
                for (auto w : neigbor) {
                    A[v][w] -= 1;
                    b[v] += a[v][w];
                }
                A[v][v] += K;
            }
        }
        auto res = linear_equation(A, b);
        if (res.empty()) cout << "impossible" << endl;
        else cout << fixed << setprecision(15) << res[s] << endl;
    }
}


int main() {
    AOJ_2171();
}
accuracy: 1
time_ms: 20
memory_kb: 3772
final_rank: 7

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

using namespace std;

#define int long long
#define rep(i, n) for(int (i)=0;(i)<(n);(i)++)
#define rrep(i, n) for(int (i)=((n)-1);(i)>=0;(i)--)
#define itn int
#define miele(v) min_element(v.begin(), v.end())
#define maele(v) max_element(v.begin(), v.end())
#define SUM(v) accumulate(v.begin(), v.end(), 0LL)
#define lb(a, key) lower_bound(a.begin(),a.end(),key)
#define ub(a, key) upper_bound(a.begin(),a.end(),key)
#define COUNT(a, key) count(a.begin(), a.end(), key)
#define BITCOUNT(x) __builtin_popcount(x)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define F first
#define S second
using P = pair<int, int>;
using WeightedGraph = vector<vector<P>>;
using UnWeightedGraph = vector<vector<int>>;
using Real = long double;
using Point = complex<Real>; //Point and Vector2d is the same!
// p.real() or real(p) -> x軸, p.imag() or imag(p) -> y軸
using Vector2d = complex<Real>;
const int MOD = 1000000007;
const long long INF = 1LL << 60;
const double EPS = 1e-15;
const double PI = 3.14159265358979323846;

template<typename T>
int getIndexOfLowerBound(vector<T> &v, T x) {
    return lower_bound(v.begin(), v.end(), x) - v.begin();
}

template<typename T>
int getIndexOfUpperBound(vector<T> &v, T x) {
    return upper_bound(v.begin(), v.end(), x) - v.begin();
}

template<class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

#define repi(itr, ds) for (auto itr = ds.begin(); itr != ds.end(); itr++)

istream &operator>>(istream &is, Point &p) {
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}

template<typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p_var) {
    is >> p_var.first >> p_var.second;
    return is;
}

template<typename T>
istream &operator>>(istream &is, vector<T> &vec) {
    for (T &x : vec) is >> x;
    return is;
}

template<typename T, typename U>
ostream &operator<<(ostream &os, pair<T, U> &pair_var) {
    os << pair_var.first << ' ' << pair_var.second;
    return os;
}

template<typename T>
ostream &operator<<(ostream &os, vector<T> &vec) {
    for (int i = 0; i < vec.size(); i++)
        os << vec[i] << ' ';
    return os;
}

template<typename T, typename U>
ostream &operator<<(ostream &os, vector<pair<T, U>> &vec) {
    for (int i = 0; i < vec.size(); i++)
        os << vec[i] << '\n';
    return os;
}

template<typename T>
ostream &operator<<(ostream &os, vector<vector<T>> &df) {
    for (auto &vec : df) os << vec;
    return os;
}

template<typename T, typename U>
ostream &operator<<(ostream &os, map<T, U> &map_var) {
    repi(itr, map_var) {
        os << *itr << ' ';
        itr++;
        itr--;
    }
    return os;
}

template<typename T>
ostream &operator<<(ostream &os, set<T> &set_var) {
    repi(itr, set_var) {
        os << *itr << ' ';
        itr++;
        itr--;
    }
    return os;
}

void print() { cout << endl; }

template<class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
    cout << head;
    if (sizeof...(tail) != 0) cout << " ";
    print(forward<Tail>(tail)...);
}

vector<double> gauss_jordan(const vector<vector<int>> &A, const vector <int> &b) {
    const double EPS = 1E-8;
    int n = A.size();
    vector <vector<double>> B(n,vector <double>(n+1));

    // [A|b]みたいになるようにBに代入
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            B[i][j] = A[i][j];
        }
    }
    for (int i = 0; i < n; ++i) {
        B[i][n] = b[i];
    }

    for (int i = 0; i < n; ++i) {
        // 注目している変数の係数の絶対値が大きいしきをi番目に持ってくる
        int pivot = i;
        for (int j = i; j < n; ++j) {
            if (abs(B[j][i]) > abs(B[pivot][i])) pivot = j;
        }
        swap(B[i], B[pivot]);

        // 解がないか、一意でない
        if (abs(B[i][i]) < EPS) {
            vector <double> res(0);
            return res;
        }
        // 注目している変数の係数を1にする
        for (int j = i+1; j <= n; ++j) {
            B[i][j] /= B[i][i];
        }
        for (int j = 0; j < n; ++j) {
            if (i != j) {
                // j 番目の式からi番目の変数を消去
                for (int k = i+1; k <= n; ++k) {
                    B[j][k] -= B[j][i] * B[i][k];
                }
            }
        }
    }
    vector <double> x(n);
    for (int i = 0; i < n; ++i) {
        x[i] = B[i][n];
    }

    return x;
}

void solve(int n, int s, int t) {
    vector <bool> has_sign(n);
    for (int i = 0; i < n; ++i) {
        int tmp; cin>>tmp;
        has_sign[i] = tmp == 1;
    }
    vector <vector<int>> a(n,vector <int>(n));
    cin>>a;

    vector <vector<int>> dist(n+10,vector <int>(n+10));

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (a[i][j] == 0) {
                dist[i][j] = 99999999;
            } else {
                dist[i][j] = a[i][j];
            }
        }
    }

    for(int k=0;k<n;k++){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i == j) dist[i][j] = 0;
                chmin(dist[i][j],dist[i][k]+dist[k][j]);
            }
        }
    }

    // Corner Case
    if (dist[s][t] == 100000) {
        cout << "impossible" << endl;
        return;
    }

    // 連立一次方程式
    vector <vector<int>> A(n,vector <int>(n));
    vector <int> b(n);

    for (int i = 0; i < n; ++i) {
        // ゴール地点
        if (i == t) {
            A[i][i] = 1;
            b[i] = 0;
            continue;
        }
        vector<int> neighbor;
        for (int j = 0; j < n; ++j) {
            if (a[i][j] == 0) continue;
            if (has_sign[i] == 1 && dist[i][t] != dist[j][t] + a[i][j]) continue;
            neighbor.push_back(j);
        }
        int K = neighbor.size();
        for (int w: neighbor) {
            A[i][w] -= 1;
            b[i] += a[i][w];
        }
        A[i][i] += K;
    }

    auto x = gauss_jordan(A, b);
    if (x.size() == 0) {
        print("impossible");
    } else {
        cout << fixed << setprecision(15) << x[s] << endl;
    }
}

signed main(void) { cin.tie(0); ios::sync_with_stdio(false);
    while(true) {
        int n, s, t; cin>>n>>s>>t;
        if (n == 0 && s == 0 && t == 0) {
            break;
        }
        s--; t--;
        solve(n, s, t);
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3880
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <iomanip>
#include <algorithm>
using namespace std;
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl


using D = double;
const D EPS = 1e-10;

template<class T> struct Matrix {
    vector<vector<T> > val;
    Matrix(int n, int m, T x = 0) : val(n, vector<T>(m, x)) {}
    void init(int n, int m, T x = 0) {val.assign(n, vector<T>(m, x));}
    size_t size() const {return val.size();}
    inline vector<T>& operator [] (int i) {return val[i];}
};

template<class T> ostream& operator << (ostream& s, Matrix<T> A) {
    s << endl; 
    for (int i = 0; i < A.size(); ++i) {
        for (int j = 0; j < A[i].size(); ++j) {
            s << A[i][j] << ", ";
        }
        s << endl;
    }
    return s;
}

template<class T> Matrix<T> operator * (Matrix<T> A, Matrix<T> B) {
    Matrix<T> R(A.size(), B[0].size());
    for (int i = 0; i < A.size(); ++i)
        for (int j = 0; j < B[0].size(); ++j)
            for (int k = 0; k < B.size(); ++k)
                R[i][j] += A[i][k] * B[k][j];
    return R;
}

template<class T> Matrix<T> pow(Matrix<T> A, long long n) {
    Matrix<T> R(A.size(), A.size());
    for (int i = 0; i < A.size(); ++i) R[i][i] = 1;
    while (n > 0) {
        if (n & 1) R = R * A;
        A = A * A;
        n >>= 1;
    }
    return R;
}

template<class T> int GaussJordan(Matrix<T> &A, bool is_extended = false) {
    int m = A.size(), n = A[0].size();
    int rank = 0;
    for (int col = 0; col < n; ++col) {
        if (is_extended && col == n-1) break;
        int pivot = -1;
        T ma = EPS;
        for (int row = rank; row < m; ++row) {
            if (abs(A[row][col]) > ma) {
                ma = abs(A[row][col]);
                pivot = row;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        auto fac = A[rank][col];
        for (int col2 = rank + 1; col2 < n; ++col2) A[rank][col2] /= fac;
        for (int row = 0; row < m; ++row) {
            if (row != rank && abs(A[row][col]) > EPS) {
                auto fac = A[row][col];
                for (int col2 = rank + 1; col2 < n; ++col2) {
                    A[row][col2] -= A[rank][col2] * fac;
                }
            }
        }
        ++rank;
    }
    return rank;
}

template<class T> vector<T> linear_equation(Matrix<T> A, vector<T> b) {
    // extended
    int m = A.size(), n = A[0].size();
    Matrix<T> M(m, n + 1);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    
    // check if it has no solution
    vector<T> res;
    for (int row = rank; row < m; ++row) if (abs(M[row][n]) > EPS) return res;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return res;
}



int N, s, t;
vector<int> q;
vector<vector<int> > a;

void solve() {
    // Dijkstra
    const int INF = 1<<29;
    vector<int> dist(N, INF);
    vector<bool> seen(N, 0);
    dist[t] = 0;
    for (int iter = 0; iter < N; ++iter) {
        int curd = INF;
        int v = -1;
        for (int i = 0; i < N; ++i) {
            if (seen[i]) continue;
            if (curd > dist[i]) {
                curd = dist[i];
                v = i;
            }
        }
        if (v == -1) break;
        for (int w = 0; w < N; ++w) {
            if (w == v) continue;
            if (a[v][w] == 0) continue;
            dist[w] = min(dist[w], curd + a[v][w]);
        }
        seen[v] = true;
    }
    if (dist[s] >= INF) {
        cout << "impossible" << endl;
        return;
    }

    // 連立一次方程式
    Matrix<D> A(N, N, 0); vector<D> b(N, 0);
    for (int v = 0; v < N; ++v) {
        if (v == t) {
            A[v][v] = 1;
            b[v] = 0;
        }
        else {
            vector<int> neigbor;
            for (int w = 0; w < N; ++w) {
                if (a[v][w] == 0) continue;
                if (q[v] == 1 && dist[w] + a[v][w] != dist[v]) continue;
                neigbor.push_back(w);
            }
            int K = neigbor.size();
            for (auto w : neigbor) {
                A[v][w] -= 1;
                b[v] += a[v][w];
            }
            A[v][v] += K;
        }
    }
    auto res = linear_equation(A, b); 
    if (res.empty()) cout << "impossible" << endl;
    else cout << fixed << setprecision(15) << res[s] << endl;
}

int main() {
    while (cin >> N >> s >> t, N) {
        --s, --t;
        q.resize(N);
        for (int i = 0; i < N; ++i) cin >> q[i];
        a.assign(N, vector<int>(N));
        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cin >> a[i][j];
        solve();
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3628
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <iomanip>
#include <algorithm>
using namespace std;
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl


using D = double;
const D EPS = 1e-10;

template<class T> struct Matrix {
    vector<vector<T> > val;
    Matrix(int n, int m, T x = 0) : val(n, vector<T>(m, x)) {}
    void init(int n, int m, T x = 0) {val.assign(n, vector<T>(m, x));}
    size_t size() const {return val.size();}
    inline vector<T>& operator [] (int i) {return val[i];}
};

template<class T> ostream& operator << (ostream& s, Matrix<T> A) {
    s << endl; 
    for (int i = 0; i < A.size(); ++i) {
        for (int j = 0; j < A[i].size(); ++j) {
            s << A[i][j] << ", ";
        }
        s << endl;
    }
    return s;
}

template<class T> Matrix<T> operator * (Matrix<T> A, Matrix<T> B) {
    Matrix<T> R(A.size(), B[0].size());
    for (int i = 0; i < A.size(); ++i)
        for (int j = 0; j < B[0].size(); ++j)
            for (int k = 0; k < B.size(); ++k)
                R[i][j] += A[i][k] * B[k][j];
    return R;
}

template<class T> Matrix<T> pow(Matrix<T> A, long long n) {
    Matrix<T> R(A.size(), A.size());
    for (int i = 0; i < A.size(); ++i) R[i][i] = 1;
    while (n > 0) {
        if (n & 1) R = R * A;
        A = A * A;
        n >>= 1;
    }
    return R;
}

template<class T> int GaussJordan(Matrix<T> &A, bool is_extended = false) {
    int m = A.size(), n = A[0].size();
    int rank = 0;
    for (int col = 0; col < n; ++col) {
        if (is_extended && col == n-1) break;
        int pivot = -1;
        T ma = EPS;
        for (int row = rank; row < m; ++row) {
            if (abs(A[row][col]) > ma) {
                ma = abs(A[row][col]);
                pivot = row;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        auto fac = A[rank][col];
        for (int col2 = 0; col2 < n; ++col2) A[rank][col2] /= fac;
        for (int row = 0; row < m; ++row) {
            if (row != rank && abs(A[row][col]) > EPS) {
                auto fac = A[row][col];
                for (int col2 = 0; col2 < n; ++col2) {
                    A[row][col2] -= A[rank][col2] * fac;
                }
            }
        }
        ++rank;
    }
    return rank;
}

template<class T> vector<T> linear_equation(Matrix<T> A, vector<T> b) {
    // extended
    int m = A.size(), n = A[0].size();
    Matrix<T> M(m, n + 1);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    
    // check if it has no solution
    vector<T> res;
    for (int row = rank; row < m; ++row) if (abs(M[row][n]) > EPS) return res;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return res;
}



int N, s, t;
vector<int> q;
vector<vector<int> > a;

void solve() {
    // Dijkstra
    const int INF = 1<<29;
    vector<int> dist(N, INF);
    vector<bool> seen(N, 0);
    dist[t] = 0;
    for (int iter = 0; iter < N; ++iter) {
        int curd = INF;
        int v = -1;
        for (int i = 0; i < N; ++i) {
            if (seen[i]) continue;
            if (curd > dist[i]) {
                curd = dist[i];
                v = i;
            }
        }
        if (v == -1) break;
        for (int w = 0; w < N; ++w) {
            if (w == v) continue;
            if (a[v][w] == 0) continue;
            dist[w] = min(dist[w], curd + a[v][w]);
        }
        seen[v] = true;
    }
    if (dist[s] >= INF) {
        cout << "impossible" << endl;
        return;
    }

    // 連立一次方程式
    Matrix<D> A(N, N, 0); vector<D> b(N, 0);
    for (int v = 0; v < N; ++v) {
        if (v == t) {
            A[v][v] = 1;
            b[v] = 0;
        }
        else {
            vector<int> neigbor;
            for (int w = 0; w < N; ++w) {
                if (a[v][w] == 0) continue;
                if (q[v] == 1 && dist[w] + a[v][w] != dist[v]) continue;
                neigbor.push_back(w);
            }
            int K = neigbor.size();
            for (auto w : neigbor) {
                A[v][w] -= 1;
                b[v] += a[v][w];
            }
            A[v][v] += K;
        }
    }
    auto res = linear_equation(A, b); 
    if (res.empty()) cout << "impossible" << endl;
    else cout << fixed << setprecision(15) << res[s] << endl;
}

int main() {
    while (cin >> N >> s >> t, N) {
        --s, --t;
        q.resize(N);
        for (int i = 0; i < N; ++i) cin >> q[i];
        a.assign(N, vector<int>(N));
        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cin >> a[i][j];
        solve();
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3784
final_rank: 8

code_snippet: #ifndef HIDDEN_IN_VS // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; // -2^63 ～ 2^63 = 9 * 10^18（int は -2^31 ～ 2^31 = 2 * 10^9）
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = acos(-1);
const vi DX = { 1, 0, -1, 0 }; // 4 近傍（下，右，上，左）
const vi DY = { 0, 1, 0, -1 };
int INF = 1001001001; ll INFL = 4004004004004004004LL;
double EPS = 1e-15;

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define lbpos(a, x) (int)distance((a).begin(), std::lower_bound(all(a), x))
#define ubpos(a, x) (int)distance((a).begin(), std::upper_bound(all(a), x))
#define Yes(b) {cout << ((b) ? "Yes\n" : "No\n");}
#define YES(b) {cout << ((b) ? "YES\n" : "NO\n");}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素（変更不可能）
#define repea(v, a) for(auto& v : (a)) // a の全要素（変更可能）
#define repb(set, d) for(int set = 0; set < (1 << int(d)); ++set) // d ビット全探索（昇順）
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て（昇順）
#define smod(n, m) ((((n) % (m)) + (m)) % (m)) // 非負mod
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去
#define EXIT(a) {cout << (a) << endl; exit(0);} // 強制終了

// 汎用関数の定義
template <class T> inline ll pow(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新（更新されたら true を返す）
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新（更新されたら true を返す）
template <class T> inline T get(T set, int i) { return (set >> i) & T(1); }

// 演算子オーバーロード
template <class T, class U> inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T> inline istream& operator>>(istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline vector<T>& operator--(vector<T>& v) { repea(x, v) --x; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { repea(x, v) ++x; return v; }

#endif // 折りたたみ用


#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;

#ifdef _MSC_VER
#include "localACL.hpp"
#endif

using mint = modint1000000007;
//using mint = modint998244353;
//using mint = modint; // mint::set_mod(m);

namespace atcoder {
	inline istream& operator>>(istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
	inline ostream& operator<<(ostream& os, const mint& x) { os << x.val(); return os; }
}
using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;
#endif


#ifdef _MSC_VER // 手元環境（Visual Studio）
#include "local.hpp"
#else // 提出用（gcc）
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(ll n) { return __builtin_popcountll(n); }
inline int lsb(int n) { return n != 0 ? __builtin_ctz(n) : -1; }
inline int lsb(ll n) { return n != 0 ? __builtin_ctzll(n) : -1; }
inline int msb(int n) { return n != 0 ? (31 - __builtin_clz(n)) : -1; }
inline int msb(ll n) { return n != 0 ? (63 - __builtin_clzll(n)) : -1; }
#define gcd __gcd
#define dump(...)
#define dumpel(v)
#define dump_list(v)
#define dump_mat(v)
#define input_from_file(f)
#define output_to_file(f)
#define Assert(b) { if (!(b)) while (1) cout << "OLE"; }
#endif


//【コスト付きグラフの辺】
/*
* to : 行き先の頂点番号
* cost : 辺のコスト
*/
struct WEdge {
	// verify : https://judge.yosupo.jp/problem/shortest_path

	int to; // 行き先の頂点番号
	ll cost; // 辺のコスト

	WEdge() : to(-1), cost(-INFL) {}
	WEdge(int to_, ll cost_) : to(to_), cost(cost_) {}

	// プレーングラフで呼ばれたとき用
	operator int() const { return to; }

#ifdef _MSC_VER
	friend ostream& operator<<(ostream& os, const WEdge& e) {
		os << '(' << e.to << ',' << e.cost << ')';
		return os;
	}
#endif
};


//【コスト付きグラフ】
/*
* WGraph g
* g[v] : 頂点 v から出る辺を並べたリスト
*
* verify : https://judge.yosupo.jp/problem/shortest_path
*/
using WGraph = vector<vector<WEdge>>;


//【単一始点最短路】O(|V| + |E| log|V|)
/*
* 非負のコスト付きグラフ g に対し，始点 st から各頂点 i への最短距離を dist[i] に格納する．
* 頂点 i に到達不能の場合は dist[i] = INFL とする．
*/
void dijkstra(const WGraph& g, int st, vl& dist) {
	// 参考 : https://snuke.hatenablog.com/entry/2021/02/22/102734
	// verify : https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/all/GRL_1_A

	int n = sz(g);
	dist = vl(n, INFL); // スタートからの最短距離
	dist[st] = 0;

	// 組 (スタートからの距離, 頂点番号) を入れる優先度付きキュー
	priority_queue_rev<pli> q;
	q.push({ 0, st });

	while (!q.empty()) {
		ll c; int s;
		tie(c, s) = q.top(); q.pop();

		// すでにより短い距離に更新されていたなら何もしない．（忘れると O(|V|^2)）
		if (dist[s] < c) continue;

		repe(e, g[s]) {
			// より短い距離で辿り着けるなら距離を更新し，その先も探索する．
			if (dist[s] + e.cost < dist[e.to]) {
				dist[e.to] = dist[s] + e.cost;
				q.push({ dist[e.to], e.to });
			}
		}
	}
}


//【行列】
/*
* Matrix<T>(int n, int m) : O(n m)
*	n×m 零行列で初期化する．
*
* Matrix<T>(int n) : O(n^2)
*	n×n 単位行列で初期化する．
*
* Matrix<T>(vvT a) : O(n m)
*	二次元配列 a[0..n)[0..m) で初期化する．
*
* bool empty() : O(1)
*	行列が空かを返す．
*
* A + B : O(n m)
*	n×m 行列 A, B の和を返す．+= も使用可．
*
* A - B : O(n m)
*	n×m 行列 A, B の差を返す．-= も使用可．
*
* c * A ／ A * c : O(n m)
*	n×m 行列 A とスカラー c のスカラー積を返す．*= も使用可．
*
* A * x : O(n m)
*	n×m 行列 A と n 次元列ベクトル x の積を返す．
*
* x * A : O(n m)
*	m 次元行ベクトル x と n×m 行列 A の積を返す．
*
* A * B : O(n m l)
*	n×m 行列 A と m×l 行列 B の積を返す．
*
* Mat pow(ll d) : O(n^3 log d)
*	自身を d 乗した行列を返す．
*/
template <class T>
struct Matrix {
	int n, m; // 行列のサイズ（n 行 m 列）
	vector<vector<T>> v; // 行列の成分

	// n×m 零行列で初期化する．
	Matrix(int n, int m) : n(n), m(m), v(n, vector<T>(m)) {}

	// n×n 単位行列で初期化する．
	Matrix(int n) : n(n), m(n), v(n, vector<T>(n)) { rep(i, n) v[i][i] = T(1); }

	// 二次元配列 a[0..n)[0..m) で初期化する．
	Matrix(const vector<vector<T>>& a) : n(sz(a)), m(sz(a[0])), v(a) {}
	Matrix() : n(0), m(0) {}

	// 代入
	Matrix(const Matrix&) = default;
	Matrix& operator=(const Matrix&) = default;

	// アクセス
	inline vector<T> const& operator[](int i) const { return v[i]; }
	inline vector<T>& operator[](int i) {
		// verify : https://judge.yosupo.jp/problem/matrix_product

		// inline を付けて [] でアクセスするとなぜか v[] への直接アクセスより速くなった．
		return v[i];
	}

	// 入力
	friend istream& operator>>(istream& is, Matrix& a) {
		rep(i, a.n) rep(j, a.m) is >> a.v[i][j];
		return is;
	}

	// 空か
	bool empty() { return min(n, m) == 0; }

	// 比較
	bool operator==(const Matrix& b) const { return n == b.n && m == b.m && v == b.v; }
	bool operator!=(const Matrix& b) const { return !(*this == b); }

	// 加算，減算，スカラー倍
	Matrix& operator+=(const Matrix& b) {
		rep(i, n) rep(j, m) v[i][j] += b[i][j];
		return *this;
	}
	Matrix& operator-=(const Matrix& b) {
		rep(i, n) rep(j, m) v[i][j] -= b[i][j];
		return *this;
	}
	Matrix& operator*=(const T& c) {
		rep(i, n) rep(j, m) v[i][j] *= c;
		return *this;
	}
	Matrix operator+(const Matrix& b) const { return Matrix(*this) += b; }
	Matrix operator-(const Matrix& b) const { return Matrix(*this) -= b; }
	Matrix operator*(const T& c) const { return Matrix(*this) *= c; }
	friend Matrix operator*(const T& c, const Matrix<T>& a) { return a * c; }
	Matrix operator-() const { return Matrix(*this) *= T(-1); }

	// 行列ベクトル積 : O(m n)
	vector<T> operator*(const vector<T>& x) const {
		vector<T> y(n);
		rep(i, n) rep(j, m)	y[i] += v[i][j] * x[j];
		return y;
	}

	// ベクトル行列積 : O(m n)
	friend vector<T> operator*(const vector<T>& x, const Matrix& a) {
		vector<T> y(a.m);
		rep(i, a.n) rep(j, a.m) y[j] += x[i] * a[i][j];
		return y;
	}

	// 積：O(n^3)
	Matrix operator*(const Matrix& b) const {
		// verify : https://judge.yosupo.jp/problem/matrix_product

		Matrix res(n, b.m);
		rep(i, res.n) rep(j, res.m) rep(k, m) res[i][j] += v[i][k] * b[k][j];
		return res;
	}
	Matrix& operator*=(const Matrix& b) { *this = *this * b; return *this; }

	// 累乗：O(n^3 log d)
	Matrix pow(ll d) const {
		Matrix res(n), pow2 = *this;
		while (d > 0) {
			if (d & 1) res *= pow2;
			pow2 *= pow2;
			d /= 2;
		}
		return res;
	}

#ifdef _MSC_VER
	friend ostream& operator<<(ostream& os, const Matrix& a) {
		rep(i, a.n) {
			os << "[";
			rep(j, a.m) os << a[i][j] << " ]"[j == a.m - 1];
			if (i < a.n - 1) os << "\n";
		}
		return os;
	}
#endif
};


//【線形方程式】O(n m min(n, m))
/*
* 与えられた n×m 行列 A と n 次元ベクトル b に対し，
* 線形方程式 A x = b の特殊解 x0（m 次元ベクトル）を返す（なければ空リスト）
* また同次形 A x = 0 の解空間の基底（m 次元ベクトル）のリストを xs に格納する．
*/
template <class T>
vector<T> gauss_jordan_elimination(const Matrix<T>& A, const vector<T>& b, vector<vector<T>>* xs = nullptr) {
	// verify : https://judge.yosupo.jp/problem/system_of_linear_equations

	int n = A.n, m = A.m;

	// v : 拡大係数行列 (A | b)
	vector<vector<T>> v(n, vector<T>(m + 1));
	rep(i, n) rep(j, m) v[i][j] = A[i][j];
	rep(i, n) v[i][m] = b[i];

	// pivots[i] : 第 i 行のピボットが第何列にあるか
	vi pivots;

	// 直前に見つけたピボットの位置
	int pi = -1, pj = -1;

	// 注目位置を v[i][j] とする．
	int i = 0, j = 0;

	while (i < n && j <= m) {
		// 同じ列の下方の行から非 0 成分を見つける．
		int i2 = i;
		while (i2 < n && v[i2][j] == 0) i2++;

		// 見つからなかったら注目位置を右に移す．
		if (i2 == n) {
			j++;
			continue;
		}

		// 見つかったら第 i 行とその行を入れ替える．
		pi = i; pj = j;
		if (i != i2) swap(v[i], v[i2]);

		// v[i][j] をピボットに選択する．
		pivots.push_back(j);

		// v[i][j] が 1 になるよう第 i 行全体を v[i][j] で割る．
		T vij_inv = T(1) / v[i][j];
		repi(j2, j, m) v[i][j2] *= vij_inv;

		// 第 i 行以外の第 j 列の成分が全て 0 になるよう第 i 行を定数倍して減じる．
		rep(i2, n) {
			if (v[i2][j] == T(0) || i2 == i) continue;

			T mul = v[i2][j];
			repi(j2, j, m) v[i2][j2] -= v[i][j2] * mul;
		}

		// 注目位置を右下に移す．
		i++; j++;
	}

	// 最後に見つかったピボットの位置が第 m 列ならば解なし．
	if (pivots.back() == m) return vector<T>();

	// A x = b の特殊解 x0 の構成（任意定数は全て 0 にする）
	vector<T> x0(m);
	int rnk = sz(pivots);
	rep(i, rnk) x0[pivots[i]] = v[i][m];

	// 同次形 A x = 0 の一般解 {x} の基底の構成（任意定数を 1-hot にする）
	if (xs != nullptr) {
		xs->clear();

		int i = 0;
		rep(j, m) {
			if (i < rnk && j == pivots[i]) {
				i++;
				continue;
			}

			vector<T> x(m, T(0));
			x[j] = 1;
			rep(i2, i) x[pivots[i2]] = -v[i2][j];
			xs->emplace_back(move(x));
		}
	}

	return x0;
}


//【重み付きランダムウォーク】
/*
* Random_walk_weighted<T>(int n) : O(1)
*	n 頂点 0 辺のグラフで初期化する．
*
* add_edge(int s, int t, T w, T p) : O(1)
*	有向辺 s→t を，重み w，選択確率 p で追加する．
*
* vT solve(int t) : O(n^3)
*	各頂点から出発し t に初めて到着するまでの経路の重みの和の期待値のリストを返す．
*	制約：どの頂点からも t に到達可能
*
* 利用：【行列】，【線形方程式】
*/
template <class T>
class Random_walk_weighted {
	int n;
	Matrix<T> mat;
	vector<T> vec;

public:
	// n 頂点 0 辺のグラフで初期化する．
	Random_walk_weighted(int n) : n(n), mat(n, n), vec(n) {
		// verify : https://onlinejudge.u-aizu.ac.jp/problems/2171

		rep(i, n) mat[i][i] = 1;
	}

	// 有向辺 s→t を，重み w，選択確率 p で追加する．
	void add_edge(int s, int t, T w, T p) {
		// verify : https://onlinejudge.u-aizu.ac.jp/problems/2171

		mat[s][t] -= p;
		vec[s] += w * p;
	}

	// 各頂点から出発し t に初めて到着するまでの経路の重みの和の期待値のリストを返す．
	vector<T> solve(int t) {
		// verify : https://onlinejudge.u-aizu.ac.jp/problems/2171

		Matrix<T> mat2(mat); vector<T> vec2(vec);
		rep(j, n) mat2[t][j] = (T)(t == j);
		vec2[t] = 0;

		vector<T> sol = gauss_jordan_elimination(mat2, vec2);

		return sol;
	}

#ifdef _MSC_VER
	friend ostream& operator<<(ostream& os, const Random_walk_weighted& rw) {
		rep(i, rw.n) {
			rep(j, rw.n) os << rw.mat[i][j] << " ";
			os << " " << rw.vec[i] << endl;
		}
		return os;
	}
#endif
}; 


void solve() {
	int n, S, T;
	cin >> n >> S >> T;
	S--; T--;

	if (n == 0) exit(0);

	vi q(n);
	cin >> q;

	vvi a(n, vi(n));
	cin >> a;

	WGraph g(n);
	rep(i, n) rep(j, n) if (a[i][j] > 0) g[i].push_back({ j, a[i][j] });

	vl dist;
	dijkstra(g, T, dist);
	dump(dist);

	if (dist[S] == INFL) {
		cout << "impossible" << endl;
		return;
	}

	Random_walk_weighted<double> rw(n);
	rep(s, n) {
		if (dist[s] == INFL) {
			rw.add_edge(s, T, (double)INFL, 1.);
		}
		else if (q[s] == 0) {
			repe(e, g[s]) rw.add_edge(s, e.to, (double)e.cost, 1. / sz(g[s]));
		}
		else {
			vector<WEdge> es;
			repe(e, g[s]) if (dist[s] == dist[e.to] + e.cost) es.push_back(e);

			repe(e, es) rw.add_edge(s, e.to, (double)e.cost, 1. / sz(es));
		}
	}
	dump(rw);

	auto res = rw.solve(T);
	dump(res);

	cout << res[S] << endl;
}


int main() {
	input_from_file("input.txt");
//	output_to_file("output.txt");

	while (true) solve();
}
accuracy: 1
time_ms: 10
memory_kb: 3840
final_rank: 4

code_snippet: /**
 *  date : 2023-05-22 19:02:14
 */

#define NDEBUG
using namespace std;

// intrinstic
#include <immintrin.h>

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfenv>
#include <cfloat>
#include <chrono>
#include <cinttypes>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <ios>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <streambuf>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

// utility
namespace Nyaan {
using ll = long long;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using V = vector<T>;
template <typename T>
using VV = vector<vector<T>>;
using vi = vector<int>;
using vl = vector<long long>;
using vd = V<double>;
using vs = V<string>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<long long>>;

template <typename T, typename U>
struct P : pair<T, U> {
  template <typename... Args>
  P(Args... args) : pair<T, U>(args...) {}

  using pair<T, U>::first;
  using pair<T, U>::second;

  P &operator+=(const P &r) {
    first += r.first;
    second += r.second;
    return *this;
  }
  P &operator-=(const P &r) {
    first -= r.first;
    second -= r.second;
    return *this;
  }
  P &operator*=(const P &r) {
    first *= r.first;
    second *= r.second;
    return *this;
  }
  template <typename S>
  P &operator*=(const S &r) {
    first *= r, second *= r;
    return *this;
  }
  P operator+(const P &r) const { return P(*this) += r; }
  P operator-(const P &r) const { return P(*this) -= r; }
  P operator*(const P &r) const { return P(*this) *= r; }
  template <typename S>
  P operator*(const S &r) const {
    return P(*this) *= r;
  }
  P operator-() const { return P{-first, -second}; }
};

using pl = P<ll, ll>;
using pi = P<int, int>;
using vp = V<pl>;

constexpr int inf = 1001001001;
constexpr long long infLL = 4004004004004004004LL;

template <typename T>
int sz(const T &t) {
  return t.size();
}

template <typename T, typename U>
inline bool amin(T &x, U y) {
  return (y < x) ? (x = y, true) : false;
}
template <typename T, typename U>
inline bool amax(T &x, U y) {
  return (x < y) ? (x = y, true) : false;
}

template <typename T>
inline T Max(const vector<T> &v) {
  return *max_element(begin(v), end(v));
}
template <typename T>
inline T Min(const vector<T> &v) {
  return *min_element(begin(v), end(v));
}
template <typename T>
inline long long Sum(const vector<T> &v) {
  return accumulate(begin(v), end(v), 0LL);
}

template <typename T>
int lb(const vector<T> &v, const T &a) {
  return lower_bound(begin(v), end(v), a) - begin(v);
}
template <typename T>
int ub(const vector<T> &v, const T &a) {
  return upper_bound(begin(v), end(v), a) - begin(v);
}

constexpr long long TEN(int n) {
  long long ret = 1, x = 10;
  for (; n; x *= x, n >>= 1) ret *= (n & 1 ? x : 1);
  return ret;
}

template <typename T, typename U>
pair<T, U> mkp(const T &t, const U &u) {
  return make_pair(t, u);
}

template <typename T>
vector<T> mkrui(const vector<T> &v, bool rev = false) {
  vector<T> ret(v.size() + 1);
  if (rev) {
    for (int i = int(v.size()) - 1; i >= 0; i--) ret[i] = v[i] + ret[i + 1];
  } else {
    for (int i = 0; i < int(v.size()); i++) ret[i + 1] = ret[i] + v[i];
  }
  return ret;
};

template <typename T>
vector<T> mkuni(const vector<T> &v) {
  vector<T> ret(v);
  sort(ret.begin(), ret.end());
  ret.erase(unique(ret.begin(), ret.end()), ret.end());
  return ret;
}

template <typename F>
vector<int> mkord(int N,F f) {
  vector<int> ord(N);
  iota(begin(ord), end(ord), 0);
  sort(begin(ord), end(ord), f);
  return ord;
}

template <typename T>
vector<int> mkinv(vector<T> &v) {
  int max_val = *max_element(begin(v), end(v));
  vector<int> inv(max_val + 1, -1);
  for (int i = 0; i < (int)v.size(); i++) inv[v[i]] = i;
  return inv;
}

vector<int> mkiota(int n) {
  vector<int> ret(n);
  iota(begin(ret), end(ret), 0);
  return ret;
}

template <typename T>
T mkrev(const T &v) {
  T w{v};
  reverse(begin(w), end(w));
  return w;
}

template <typename T>
bool nxp(vector<T> &v) {
  return next_permutation(begin(v), end(v));
}

template <typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

}  // namespace Nyaan

// bit operation
namespace Nyaan {
__attribute__((target("popcnt"))) inline int popcnt(const u64 &a) {
  return _mm_popcnt_u64(a);
}
inline int lsb(const u64 &a) { return a ? __builtin_ctzll(a) : 64; }
inline int ctz(const u64 &a) { return a ? __builtin_ctzll(a) : 64; }
inline int msb(const u64 &a) { return a ? 63 - __builtin_clzll(a) : -1; }
template <typename T>
inline int gbit(const T &a, int i) {
  return (a >> i) & 1;
}
template <typename T>
inline void sbit(T &a, int i, bool b) {
  if (gbit(a, i) != b) a ^= T(1) << i;
}
constexpr long long PW(int n) { return 1LL << n; }
constexpr long long MSK(int n) { return (1LL << n) - 1; }
}  // namespace Nyaan

// inout
namespace Nyaan {

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>
istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  int s = (int)v.size();
  for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
  return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (auto &x : v) is >> x;
  return is;
}

istream &operator>>(istream &is, __int128_t &x) {
  string S;
  is >> S;
  x = 0;
  int flag = 0;
  for (auto &c : S) {
    if (c == '-') {
      flag = true;
      continue;
    }
    x *= 10;
    x += c - '0';
  }
  if (flag) x = -x;
  return is;
}

istream &operator>>(istream &is, __uint128_t &x) {
  string S;
  is >> S;
  x = 0;
  for (auto &c : S) {
    x *= 10;
    x += c - '0';
  }
  return is;
}

ostream &operator<<(ostream &os, __int128_t x) {
  if (x == 0) return os << 0;
  if (x < 0) os << '-', x = -x;
  string S;
  while (x) S.push_back('0' + x % 10), x /= 10;
  reverse(begin(S), end(S));
  return os << S;
}
ostream &operator<<(ostream &os, __uint128_t x) {
  if (x == 0) return os << 0;
  string S;
  while (x) S.push_back('0' + x % 10), x /= 10;
  reverse(begin(S), end(S));
  return os << S;
}

void in() {}
template <typename T, class... U>
void in(T &t, U &...u) {
  cin >> t;
  in(u...);
}

void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T &t, const U &...u) {
  cout << t;
  if (sizeof...(u)) cout << sep;
  out(u...);
}

struct IoSetupNya {
  IoSetupNya() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    cerr << fixed << setprecision(7);
  }
} iosetupnya;

}  // namespace Nyaan

// debug

#ifdef NyaanDebug
#define trc(...) (void(0))
#else
#define trc(...) (void(0))
#endif

#ifdef NyaanLocal
#define trc2(...) (void(0))
#else
#define trc2(...) (void(0))
#endif

// macro
#define each(x, v) for (auto&& x : v)
#define each2(x, y, v) for (auto&& [x, y] : v)
#define all(v) (v).begin(), (v).end()
#define rep(i, N) for (long long i = 0; i < (long long)(N); i++)
#define repr(i, N) for (long long i = (long long)(N)-1; i >= 0; i--)
#define rep1(i, N) for (long long i = 1; i <= (long long)(N); i++)
#define repr1(i, N) for (long long i = (N); (long long)(i) > 0; i--)
#define reg(i, a, b) for (long long i = (a); i < (b); i++)
#define regr(i, a, b) for (long long i = (b)-1; i >= (a); i--)
#define fi first
#define se second
#define ini(...)   \
  int __VA_ARGS__; \
  in(__VA_ARGS__)
#define inl(...)         \
  long long __VA_ARGS__; \
  in(__VA_ARGS__)
#define ins(...)      \
  string __VA_ARGS__; \
  in(__VA_ARGS__)
#define in2(s, t)                           \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i]);                         \
  }
#define in3(s, t, u)                        \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i], u[i]);                   \
  }
#define in4(s, t, u, v)                     \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i], u[i], v[i]);             \
  }
#define die(...)             \
  do {                       \
    Nyaan::out(__VA_ARGS__); \
    return;                  \
  } while (0)

namespace Nyaan {
void solve();
}
int main() { Nyaan::solve(); }

//


template <typename T>
struct edge {
  int src, to;
  T cost;

  edge(int _to, T _cost) : src(-1), to(_to), cost(_cost) {}
  edge(int _src, int _to, T _cost) : src(_src), to(_to), cost(_cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T>>;
template <typename T>
using WeightedGraph = vector<Edges<T>>;
using UnweightedGraph = vector<vector<int>>;

// Input of (Unweighted) Graph
UnweightedGraph graph(int N, int M = -1, bool is_directed = false,
                      bool is_1origin = true) {
  UnweightedGraph g(N);
  if (M == -1) M = N - 1;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    if (is_1origin) x--, y--;
    g[x].push_back(y);
    if (!is_directed) g[y].push_back(x);
  }
  return g;
}

// Input of Weighted Graph
template <typename T>
WeightedGraph<T> wgraph(int N, int M = -1, bool is_directed = false,
                        bool is_1origin = true) {
  WeightedGraph<T> g(N);
  if (M == -1) M = N - 1;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    cin >> c;
    if (is_1origin) x--, y--;
    g[x].emplace_back(x, y, c);
    if (!is_directed) g[y].emplace_back(y, x, c);
  }
  return g;
}

// Input of Edges
template <typename T>
Edges<T> esgraph(int N, int M, int is_weighted = true, bool is_1origin = true) {
  Edges<T> es;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    if (is_weighted)
      cin >> c;
    else
      c = 1;
    if (is_1origin) x--, y--;
    es.emplace_back(x, y, c);
  }
  return es;
}

// Input of Adjacency Matrix
template <typename T>
vector<vector<T>> adjgraph(int N, int M, T INF, int is_weighted = true,
                           bool is_directed = false, bool is_1origin = true) {
  vector<vector<T>> d(N, vector<T>(N, INF));
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    if (is_weighted)
      cin >> c;
    else
      c = 1;
    if (is_1origin) x--, y--;
    d[x][y] = c;
    if (!is_directed) d[y][x] = c;
  }
  return d;
}

/**
 * @brief グラフテンプレート
 * @docs docs/graph/graph-template.md
 */

// unreachable -> -1
template <typename T>
vector<T> dijkstra(WeightedGraph<T> &g, int start = 0) {
  using P = pair<T, int>;
  int N = (int)g.size();
  vector<T> d(N, T(-1));
  priority_queue<P, vector<P>, greater<P> > Q;
  d[start] = 0;
  Q.emplace(0, start);
  while (!Q.empty()) {
    P p = Q.top();
    Q.pop();
    int cur = p.second;
    if (d[cur] < p.first) continue;
    for (auto dst : g[cur]) {
      if (d[dst] == T(-1) || d[cur] + dst.cost < d[dst]) {
        d[dst] = d[cur] + dst.cost;
        Q.emplace(d[dst], dst);
      }
    }
  }
  return d;
}

/**
 * @brief ダイクストラ法
 * @docs docs/shortest-path/dijkstra.md
 */

//


using namespace std;

// {rank, det(非正方行列の場合は未定義)} を返す
// 型が double や Rational でも動くはず？(未検証)
//
// pivot 候補 : [0, pivot_end)
template <typename T>
std::pair<int, T> GaussElimination(vector<vector<T>> &a, int pivot_end = -1,
                                   bool diagonalize = false) {
  int H = a.size(), W = a[0].size(), rank = 0;
  if (pivot_end == -1) pivot_end = W;
  T det = 1;
  for (int j = 0; j < pivot_end; j++) {
    int idx = -1;
    for (int i = rank; i < H; i++) {
      if (a[i][j] != T(0)) {
        idx = i;
        break;
      }
    }
    if (idx == -1) {
      det = 0;
      continue;
    }
    if (rank != idx) det = -det, swap(a[rank], a[idx]);
    det *= a[rank][j];
    if (diagonalize && a[rank][j] != T(1)) {
      T coeff = T(1) / a[rank][j];
      for (int k = j; k < W; k++) a[rank][k] *= coeff;
    }
    int is = diagonalize ? 0 : rank + 1;
    for (int i = is; i < H; i++) {
      if (i == rank) continue;
      if (a[i][j] != T(0)) {
        T coeff = a[i][j] / a[rank][j];
        for (int k = j; k < W; k++) a[i][k] -= a[rank][k] * coeff;
      }
    }
    rank++;
  }
  return make_pair(rank, det);
}

// 解が存在する場合は, 解が v + C_1 w_1 + ... + C_k w_k と表せるとして
// (v, w_1, ..., w_k) を返す
// 解が存在しない場合は空のベクトルを返す
//
// double や Rational でも動くはず？(未検証)
template <typename T>
vector<vector<T>> LinearEquation(vector<vector<T>> a, vector<T> b) {
  int H = a.size(), W = a[0].size();
  for (int i = 0; i < H; i++) a[i].push_back(b[i]);
  auto p = GaussElimination(a, W, true);
  int rank = p.first;
  for (int i = rank; i < H; ++i) {
    if (a[i][W] != 0) return vector<vector<T>>{};
  }
  vector<vector<T>> res(1, vector<T>(W));
  vector<int> pivot(W, -1);
  for (int i = 0, j = 0; i < rank; ++i) {
    while (a[i][j] == 0) ++j;
    res[0][j] = a[i][W], pivot[j] = i;
  }
  for (int j = 0; j < W; ++j) {
    if (pivot[j] == -1) {
      vector<T> x(W);
      x[j] = 1;
      for (int k = 0; k < j; ++k) {
        if (pivot[k] != -1) x[k] = -a[pivot[k]][j];
      }
      res.push_back(x);
    }
  }
  return res;
}

using namespace Nyaan;

void q() {
  int N, S, T;
  for (; cin >> N >> S >> T, N;) {
    --S, --T;
    vl q(N);
    in(q);
    vvi A(N, vi(N));
    in(A);

    WeightedGraph<int> g(N);
    rep(i, N) rep(j, N) if (A[i][j]) g[i].emplace_back(i, j, A[i][j]);
    vi d = dijkstra(g, T);
    trc(d);
    if (d[S] == -1) {
      out("impossible");
      continue;
    }
    VV<double> m(N, V<double>(N));
    V<double> b(N);
    rep(i, N) {
      if (i == T) {
        m[i][i] = 1;
        continue;
      }
      vi dst;
      if (q[i]) {
        rep(j, N) {
          if (A[i][j] and d[i] == d[j] + A[i][j]) dst.push_back(j);
        }
      } else {
        rep(j, N) {
          if (A[i][j]) dst.push_back(j);
        }
      }
      trc(i, dst);
      double num = sz(dst);
      // (sum_{j in dst} (E_j + A_{i,j}) / num) = E_i
      each(j, dst) {
        m[i][j] += 1.0 / num;
        b[i] -= A[i][j] / num;
      }
      m[i][i] += -1.0;
    }
    auto ans = LinearEquation(m, b)[0];
    trc(ans);
    out(ans[S]);
  }
}

void Nyaan::solve() {
  int t = 1;
  // in(t);
  while (t--) q();
}
accuracy: 1
time_ms: 10
memory_kb: 3948
final_rank: 9

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

using ll = long long;
using ld = double;

const ll INF = 1001001001001001001ll;
const ld EPS = 1e-8;

class Warshall_Floyd{
    vector<vector<ll>> dist;
    int size;

    public:
    Warshall_Floyd(int N) : size(N), dist(N, vector<ll>(N, INF)){
        for(int i = 0; i < N; i++) dist[i][i] = 0;
    }
    void add_edge(int u, int v, ll w){
        dist[u][v] = w;
    }
    bool solve(){
        for(int k = 0; k < size; k++){
            for(int i = 0; i < size; i++){
                for(int j = 0; j < size; j++){
                    if(dist[i][k] == INF || dist[k][j] == INF) continue;
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
        for(int i = 0; i < size; i++)
            if(dist[i][i] < 0) return false;
        return true;
    }
    ll find_dist(int u, int v){
        return dist[u][v];
    }
    bool need_edge(int u, int v, ll w){
        for(int i = 0; i < size; i++){
            if(i == u || i == v) continue;
            if(w >= dist[u][i] + dist[i][v]) return false;
        }
        return true;
    }
};

template<class T> int GaussJordan(vector<vector<T>> &A, bool is_extended = false) {
    int m = A.size(), n = A[0].size();
    int rank = 0;
    for (int col = 0; col < n; ++col) {
        // 拡大係数行列の場合は最後の列は掃き出ししない
        if (is_extended && col == n-1) break;

        // ピボットを探す
        int pivot = -1;
        T ma = EPS;
        for (int row = rank; row < m; ++row) {
            if (abs(A[row][col]) > ma) {
                ma = abs(A[row][col]);
                pivot = row;
            }
        }
        // ピボットがなかったら次の列へ
        if (pivot == -1) continue;

        // まずは行を swap
        swap(A[pivot], A[rank]);

        // ピボットの値を 1 にする
        auto fac = A[rank][col];
        for (int col2 = 0; col2 < n; ++col2) A[rank][col2] /= fac;

        // ピボットのある列の値がすべて 0 になるように掃き出す
        for (int row = 0; row < m; ++row) {
            if (row != rank && abs(A[row][col]) > EPS) {
                auto fac = A[row][col];
                for (int col2 = 0; col2 < n; ++col2) {
                    A[row][col2] -= A[rank][col2] * fac;
                }
            }
        }
        ++rank;
    }
    return rank;
}

template<class T> vector<T> linear_equation(vector<vector<T>> A, vector<T> b) {
    // extended
    int m = A.size(), n = A[0].size();
    vector<vector<T>> M(m, vector<T>(n + 1));
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    
    // check if it has no solution
    vector<T> res;
    for (int row = rank; row < m; ++row) if (abs(M[row][n]) > EPS) return res;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return res;
}

int main(){
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    
    while(1){
        int N, S, T; cin >> N >> S >> T; S--, T--;
        if(N == 0) break;
        vector<int> Q(N); for(int i = 0; i < N; i++) cin >> Q[i];
        vector<vector<ll>> G(N, vector<ll>(N));
        Warshall_Floyd WF(N);

        for(int i = 0; i < N; i++){
            for(int j = 0; j < N; j++){
                cin >> G[i][j];
                if(G[i][j] == 0) continue;
                WF.add_edge(i, j, G[i][j]);
            }
        }

        WF.solve();

        if(WF.find_dist(S, T) >= INF){
            cout << "impossible" << endl;
            continue;
        }

        vector<vector<ld>> A(N, vector<ld>(N));
        vector<ld> B(N);
        for(int i = 0; i < N; i++){
            A[i][i] = 1;
            if(i == T) continue;

            vector<int> arr;
            for(int j = 0; j < N; j++){
                if(G[i][j]){
                    if(Q[i]){
                        if(WF.find_dist(i, T) == G[i][j] + WF.find_dist(j, T))
                            arr.emplace_back(j);
                    }
                    else arr.emplace_back(j);
                }
            }

            A[i][i] = arr.size();
            for(auto it : arr){
                A[i][it] = -1;
                B[i] += G[i][it];
            }
        }

        vector<ld> ans = linear_equation(A, B);
        cout << ans[S] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3992
final_rank: 13

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

using ll = long long;
using ld = long double;

const ll INF = 1001001001001001001ll;
const ld EPS = 1e-10;

class Warshall_Floyd{
    vector<vector<ll>> dist;
    int size;

    public:
    Warshall_Floyd(int N) : size(N), dist(N, vector<ll>(N, INF)){
        for(int i = 0; i < N; i++) dist[i][i] = 0;
    }
    void add_edge(int u, int v, ll w){
        dist[u][v] = w;
    }
    bool solve(){
        for(int k = 0; k < size; k++){
            for(int i = 0; i < size; i++){
                for(int j = 0; j < size; j++){
                    if(dist[i][k] == INF || dist[k][j] == INF) continue;
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
        for(int i = 0; i < size; i++)
            if(dist[i][i] < 0) return false;
        return true;
    }
    ll find_dist(int u, int v){
        return dist[u][v];
    }
    bool need_edge(int u, int v, ll w){
        for(int i = 0; i < size; i++){
            if(i == u || i == v) continue;
            if(w >= dist[u][i] + dist[i][v]) return false;
        }
        return true;
    }
};

template<class T> int GaussJordan(vector<vector<T>> &A, bool is_extended = false) {
    int m = A.size(), n = A[0].size();
    int rank = 0;
    for (int col = 0; col < n; ++col) {
        // 拡大係数行列の場合は最後の列は掃き出ししない
        if (is_extended && col == n-1) break;

        // ピボットを探す
        int pivot = -1;
        T ma = EPS;
        for (int row = rank; row < m; ++row) {
            if (abs(A[row][col]) > ma) {
                ma = abs(A[row][col]);
                pivot = row;
            }
        }
        // ピボットがなかったら次の列へ
        if (pivot == -1) continue;

        // まずは行を swap
        swap(A[pivot], A[rank]);

        // ピボットの値を 1 にする
        auto fac = A[rank][col];
        for (int col2 = 0; col2 < n; ++col2) A[rank][col2] /= fac;

        // ピボットのある列の値がすべて 0 になるように掃き出す
        for (int row = 0; row < m; ++row) {
            if (row != rank && abs(A[row][col]) > EPS) {
                auto fac = A[row][col];
                for (int col2 = 0; col2 < n; ++col2) {
                    A[row][col2] -= A[rank][col2] * fac;
                }
            }
        }
        ++rank;
    }
    return rank;
}

template<class T> vector<T> linear_equation(vector<vector<T>> A, vector<T> b) {
    // extended
    int m = A.size(), n = A[0].size();
    vector<vector<T>> M(m, vector<T>(n + 1));
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    
    // check if it has no solution
    vector<T> res;
    for (int row = rank; row < m; ++row) if (abs(M[row][n]) > EPS) return res;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return res;
}

int main(){
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    
    while(1){
        int N, S, T; cin >> N >> S >> T; S--, T--;
        if(N == 0) break;
        vector<int> Q(N); for(int i = 0; i < N; i++) cin >> Q[i];
        vector<vector<ll>> G(N, vector<ll>(N));
        Warshall_Floyd WF(N);

        for(int i = 0; i < N; i++){
            for(int j = 0; j < N; j++){
                cin >> G[i][j];
                if(G[i][j] == 0) continue;
                WF.add_edge(i, j, G[i][j]);
            }
        }

        WF.solve();

        if(WF.find_dist(S, T) >= INF){
            cout << "impossible" << endl;
            continue;
        }

        vector<vector<ld>> A(N, vector<ld>(N));
        vector<ld> B(N);
        for(int i = 0; i < N; i++){
            A[i][i] = 1;
            if(i == T) continue;

            vector<int> arr;
            for(int j = 0; j < N; j++){
                if(G[i][j]){
                    if(Q[i]){
                        if(WF.find_dist(i, T) == G[i][j] + WF.find_dist(j, T))
                            arr.emplace_back(j);
                    }
                    else arr.emplace_back(j);
                }
            }

            A[i][i] = arr.size();
            for(auto it : arr){
                A[i][it] = -1;
                B[i] += G[i][it];
            }
        }

        vector<ld> ans = linear_equation(A, B);
        cout << ans[S] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4112
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std ;
#define fast_io ios::sync_with_stdio(false); cin.tie(nullptr);
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
typedef long long ll ;
typedef long double ld ;
typedef pair<ll,ll> P ;
typedef tuple<ll,ll,ll> TP ;
#define chmin(a,b) a = min(a,b)
#define chmax(a,b) a = max(a,b)
#define bit_count(x) __builtin_popcountll(x)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a / gcd(a,b) * b
#define rep(i,n) for(int i = 0 ; i < n ; i++)
#define rrep(i,a,b) for(int i = a ; i < b ; i++)
#define repi(it,S) for(auto it = S.begin() ; it != S.end() ; it++)
#define pt(a) cout << a << endl
#define DEBUG(...) ; cout << #__VA_ARGS__ << endl ; for(auto x : {__VA_ARGS__}) cout << x << "  " ; cout << endl ;
#define DEBUG_LIST(...) cout << #__VA_ARGS__ << endl ; DEBUG_REP(__VA_ARGS__) ;
#define DEBUG_REP(V) cout << "{ " ; repi(itr,V) cout << *itr << ", " ; cout << "}" << endl ;
#define debug(a) cout << #a << " " << a << endl
#define all(a) a.begin(), a.end()
#define endl "\n"

template<typename T = ll> struct Matrix{
    int row, col;
    vector<vector<T>> mat ;

    private:
        void init_(vector<vector<T>> A){
            row = A.size();
            col = A[0].size();
            mat = A;
        }
        
        void init_(vector<T> A, bool row_matrix = false){
            if(row_matrix) {
                col = (int)A.size();
                row = 1;
                mat.resize(1);
                mat[0] = A;
            }
            else {
                col = 1;
                row = (int)A.size();
                mat.resize(row,vector<T>(1));
                rep(i,row) mat[i][0] = A[i];
            }
        }

        Matrix<T> pow_(ll k){
            assert(row == col);
            vector<vector<T>> E(row,vector<T>(row,0));
            rep(i,row) rep(j,row) if(i == j) E[i][j] = 1;
            Matrix<T> res(E);
            Matrix<T> X(mat);
            while(k > 0){
                if(k & 1) res *= X;
                X *= X;
                k >>= 1 ;
            }
            return res;
        }

        void transpose_() {
            vector<vector<T>> res(col,vector<T>(row));
            rep(i,row) rep(j,col) res[j][i] = mat[i][j];
            swap(row,col);
            mat = res;
        }

        void concat_col_(vector<T> &Y) {
            Matrix X(Y);
            concat_col_(X);
        }
        void concat_col_(vector<vector<T>> &Y) {
            Matrix X(Y);
            concat_col_(X);
        }
        void concat_col_(Matrix &Y) {
            assert((int)Y.row == row);
            col += Y.col;
            rep(i,row) {
                rep(j,Y.col) mat[i].push_back(Y.mat[i][j]);
            }
        }

        void concat_row_(vector<T> &Y) {
            Matrix X(Y,true);
            concat_row_(X);
        }
        void concat_row_(vector<vector<T>> &Y) {
            Matrix X(Y);
            concat_row_(X);
        }
        void concat_row_(Matrix &Y) {
            assert((int)Y.col == col);
            row += Y.row;
            rep(i,Y.row) mat.push_back(Y.mat[i]);
        }

        void print_() {
            rep(i,row){
                rep(j,col) cout << mat[i][j] << " "; cout << endl;
            }
        }

    public:

        inline Matrix &operator+=(const Matrix Y) {
            rep(i,row) rep(j,col) mat[i][j] += Y.mat[i][j];
            return *this ;
        }

        inline Matrix &operator-=(const Matrix Y) {
            rep(i,row) rep(j,col) mat[i][j] -= Y.mat[i][j];
            return *this ;
        }

        inline Matrix &operator*=(const Matrix Y) {
            int x = row, y = Y.col, n = col;
            vector<vector<T>> res(x,vector<T>(y));
            rep(i,x) rep(j,y) rep(k,n) res[i][j] += mat[i][k] * Y.mat[k][j];
            swap(mat,res);
            return *this ;
        }

        inline Matrix operator-() const {
            rep(i,row) rep(j,col) mat[i][j] *= -1;
            return *this ;
        }

        inline Matrix operator+(const Matrix Y) const { return Matrix(*this) += Y; }

        inline Matrix operator-(const Matrix Y) const { return Matrix(*this) -= Y; }

        inline Matrix operator*(const Matrix Y) const { return Matrix(*this) *= Y; }

        inline bool operator==(const Matrix Y) const { return mat == Y.mat; }

        inline bool operator!=(const Matrix Y) const { return mat != Y.mat; }

        inline vector<T>&operator[](int i) { return mat[i] ; }

        Matrix(int n): row(n), col(0) { mat.resize(row); }
        Matrix(vector<T> A, bool row_matrix = false) { init_(A, row_matrix); }
        Matrix(vector<vector<T>> A){ init_(A); }
        void init(vector<T> A, bool row_matrix = false) { init_(A, row_matrix); }
        void init(vector<vector<T>> A) { init_(A); }
        size_t row_size() { return row; }
        size_t col_size() { return col; }
        Matrix pow(ll k){ return pow_(k); }
        void transpose() { transpose_(); }
        void concat_col(vector<vector<T>> &Y) { concat_col_(Y); }
        void concat_col(vector<T> &Y) { concat_col_(Y); }
        void concat_col(Matrix &Y) { concat_col_(Y); }
        void concat_row(vector<vector<T>> &Y) { concat_row_(Y); }
        void concat_row(vector<T> &Y) { concat_row_(Y); }
        void concat_row(Matrix &Y) { concat_row_(Y); }
        void print() { print_(); }
};

// 誤差
template<typename T> struct GaussJordan{

    const double EPS = 1e-10 ;

    private:

        int rank;
        vector<T> solution;

        Matrix<T> to_matrix(vector<vector<T>> A){
            Matrix M(A);
            return M;
        }

        Matrix<T> to_matrix(vector<T> A, bool row_mat=false){
            Matrix M(A, row_mat);
            return M;
        }

        // 階数（Rank）を返す  (注意 : 参照渡しのためmatrixも変化する)
        // mat : 行列 , is_extended : 拡大係数行列かどうか
        int sweep_out_(Matrix<T> &mat, bool is_extended){

            // 行列の条件
            int n = mat.row , m = mat.col;
            // 階数
            rank = 0 ;

            for(int col = 0 ; col < m ; col++){
                // 拡大係数行列の場合、最後の列は何もしない
                if(is_extended && col == m - 1) break ;

                // ピボットを探す
                int pivot = -1 ;
                T e = EPS ;
                for(int row = rank ; row < n ; row++){
                    if(abs(mat[row][col]) > e){
                        e = abs(mat[row][col]) ;
                        pivot = row ;
                    }
                }

                // ピボットがなかったら次の列へ
                if(pivot == -1) continue ;

                // 行をスワップする
                swap(mat[rank] , mat[pivot]) ;

                // ピボットの値を1にする（このあとの演算のため）
                auto fac = mat[rank][col] ;
                for(int col2 = 0 ; col2 < m ; col2++) mat[rank][col2] /= fac ;

                // 今見ている列を掃き出す
                for(int row = 0 ; row < n ; row++){
                    // 見てる行が基準の行でない && 値が1e-10より大きい
                    if(row != rank && abs(mat[row][col]) > EPS){
                        // 列基本操作
                        auto fac = mat[row][col] ;
                        for(int col2 = 0 ; col2 < m ; col2++){
                            mat[row][col2] -= mat[rank][col2] * fac ;
                        }
                    }
                }
                rank++ ;
            }
            return rank ;
        }

        vector<T> solve_simultaneous_equation_(vector<vector<T>> &A , vector<T> &b){
            return solve_simultaneous_equation_(to_matrix(A), to_matrix(b));
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &A , vector<T> &b){
            return solve_simultaneous_equation_(A, to_matrix(b));
        }
        vector<T> solve_simultaneous_equation_(vector<vector<T>> &A , Matrix<T> &b){
            return solve_simultaneous_equation_(to_matrix(A), b);
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &A , Matrix<T> &b){
            A.concat_col(b);
            return solve_simultaneous_equation_(A);
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &M){
            int n = M.row, m = M.col;
            int rank = sweep_out(M,true);

            // 解があるかの確認（行列の階数より上の領域で解があるとおかしい）
            for(int row = rank ; row < n ; row++) if(abs(M[row][m]) > EPS) return {};

            // 答え
            vector<T> res(rank,0) ;
            for(int i = 0 ; i < rank ; i++) res[i] = M[i][m-1] ;

            return solution = res;
        }

    public:
        GaussJordan(){}
        int sweep_out(Matrix<T> &A) { return sweep_out_(A, false); }
        int sweep_out(Matrix<T> &A, bool is_extended) { return sweep_out_(A, is_extended); }
        vector<T> solve_simultaneous_equation(Matrix<T> &A , Matrix<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(Matrix<T> &A , vector<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(vector<vector<T>> &A , vector<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(vector<vector<T>> &A , Matrix<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(Matrix<T> A) { return solve_simultaneous_equation_(A); }
        int get_rank() { return rank; }
        vector<T> get_solution() { return solution; }
};

int n, s, t;

struct edge{
    int to ;
    ll cost ;
};

vector<vector<edge>> G;
vector<vector<edge>> F;
ll d[202] ;
int A[202];
int prevv[202] ; // 一個前のノード
vector<int> line ; // 経路復元

// 始点: s , 終点: t
void djikstra(int s){
    rep(i,n) d[i] = 1e16 ;
    rep(i,n) prevv[i] = -1 ;
    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 dist = p.first;
        int v = p.second;
        if(d[v] < dist) continue;
        for(int i = 0 ; i < G[v].size() ; i++){
            edge e = G[v][i] ;
            if(d[e.to] > d[v] + e.cost){
                d[e.to] = d[v] + e.cost ;
                prevv[e.to] = v ;
                que.push(P(d[e.to],e.to)) ;
            }
        }
    }
}

int main(){
    fast_io
    while(true){
        F.clear();
        G.clear();
        cin >> n >> s >> t;
        G.resize(n);
        F.resize(n);
        if(n == 0 && s == 0 && t == 0) break;
        s--; t--;
        rep(i,n) cin >> A[i];
        rep(i,n) rep(j,n){
            int a;
            cin >> a;
            if(a == 0) continue;
            G[i].push_back({j,a});
        }
        djikstra(t);
        if(d[s] == 1e16){
            cout << "impossible" << endl;
            return 0;
        }
        rep(i,n){
            int minval = 1e9;
            vector<edge> vec;
            for(edge e : G[i]){
                int u = e.to;
                if(minval > d[u] + e.cost){
                    minval = d[u] + e.cost;
                    vec = {};
                    vec.push_back({u, e.cost});
                }
                else if(minval == d[u] + e.cost){
                    vec.push_back({u, e.cost});
                }
            }
            F[i] = vec;
        }
        vector<vector<ld>> mat(n,vector<ld>(n+1,0));
        rep(i,n){
            if(i == t){
                mat[i][i] = 1;
                continue;
            }
            if(A[i]){
                int m = F[i].size();
                ld w = 0;
                mat[i][i] = m;
                for(edge e : F[i]){
                    mat[i][e.to] = -1;
                    w += e.cost;
                }
                mat[i][n] = w;
            }
            else{
                int m = G[i].size();
                ld w = 0;
                mat[i][i] = m;
                for(edge e :G[i]){
                    mat[i][e.to] = -1;
                    w += e.cost;
                }
                mat[i][n] = w;
            }
        }
        GaussJordan<ld> gj;
        vector<ld> res = gj.solve_simultaneous_equation(Matrix<ld>(mat));
        cout << fixed << setprecision(25) << res[s] << endl;
    }
}
accuracy: 1
time_ms: 20
memory_kb: 4364
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std ;
#define fast_io ios::sync_with_stdio(false); cin.tie(nullptr);
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
typedef long long ll ;
typedef long double ld ;
typedef pair<ll,ll> P ;
typedef tuple<ll,ll,ll> TP ;
#define chmin(a,b) a = min(a,b)
#define chmax(a,b) a = max(a,b)
#define bit_count(x) __builtin_popcountll(x)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a / gcd(a,b) * b
#define rep(i,n) for(int i = 0 ; i < n ; i++)
#define rrep(i,a,b) for(int i = a ; i < b ; i++)
#define repi(it,S) for(auto it = S.begin() ; it != S.end() ; it++)
#define pt(a) cout << a << endl
#define DEBUG(...) ; cout << #__VA_ARGS__ << endl ; for(auto x : {__VA_ARGS__}) cout << x << "  " ; cout << endl ;
#define DEBUG_LIST(...) cout << #__VA_ARGS__ << endl ; DEBUG_REP(__VA_ARGS__) ;
#define DEBUG_REP(V) cout << "{ " ; repi(itr,V) cout << *itr << ", " ; cout << "}" << endl ;
#define debug(a) cout << #a << " " << a << endl
#define all(a) a.begin(), a.end()
#define endl "\n"

template<typename T = ll> struct Matrix{
    int row, col;
    vector<vector<T>> mat ;

    private:
        void init_(vector<vector<T>> A){
            row = A.size();
            col = A[0].size();
            mat = A;
        }
        
        void init_(vector<T> A, bool row_matrix = false){
            if(row_matrix) {
                col = (int)A.size();
                row = 1;
                mat.resize(1);
                mat[0] = A;
            }
            else {
                col = 1;
                row = (int)A.size();
                mat.resize(row,vector<T>(1));
                rep(i,row) mat[i][0] = A[i];
            }
        }

        Matrix<T> pow_(ll k){
            assert(row == col);
            vector<vector<T>> E(row,vector<T>(row,0));
            rep(i,row) rep(j,row) if(i == j) E[i][j] = 1;
            Matrix<T> res(E);
            Matrix<T> X(mat);
            while(k > 0){
                if(k & 1) res *= X;
                X *= X;
                k >>= 1 ;
            }
            return res;
        }

        void transpose_() {
            vector<vector<T>> res(col,vector<T>(row));
            rep(i,row) rep(j,col) res[j][i] = mat[i][j];
            swap(row,col);
            mat = res;
        }

        void concat_col_(vector<T> &Y) {
            Matrix X(Y);
            concat_col_(X);
        }
        void concat_col_(vector<vector<T>> &Y) {
            Matrix X(Y);
            concat_col_(X);
        }
        void concat_col_(Matrix &Y) {
            assert((int)Y.row == row);
            col += Y.col;
            rep(i,row) {
                rep(j,Y.col) mat[i].push_back(Y.mat[i][j]);
            }
        }

        void concat_row_(vector<T> &Y) {
            Matrix X(Y,true);
            concat_row_(X);
        }
        void concat_row_(vector<vector<T>> &Y) {
            Matrix X(Y);
            concat_row_(X);
        }
        void concat_row_(Matrix &Y) {
            assert((int)Y.col == col);
            row += Y.row;
            rep(i,Y.row) mat.push_back(Y.mat[i]);
        }

        void print_() {
            rep(i,row){
                rep(j,col) cout << mat[i][j] << " "; cout << endl;
            }
        }

    public:

        inline Matrix &operator+=(const Matrix Y) {
            rep(i,row) rep(j,col) mat[i][j] += Y.mat[i][j];
            return *this ;
        }

        inline Matrix &operator-=(const Matrix Y) {
            rep(i,row) rep(j,col) mat[i][j] -= Y.mat[i][j];
            return *this ;
        }

        inline Matrix &operator*=(const Matrix Y) {
            int x = row, y = Y.col, n = col;
            vector<vector<T>> res(x,vector<T>(y));
            rep(i,x) rep(j,y) rep(k,n) res[i][j] += mat[i][k] * Y.mat[k][j];
            swap(mat,res);
            return *this ;
        }

        inline Matrix operator-() const {
            rep(i,row) rep(j,col) mat[i][j] *= -1;
            return *this ;
        }

        inline Matrix operator+(const Matrix Y) const { return Matrix(*this) += Y; }

        inline Matrix operator-(const Matrix Y) const { return Matrix(*this) -= Y; }

        inline Matrix operator*(const Matrix Y) const { return Matrix(*this) *= Y; }

        inline bool operator==(const Matrix Y) const { return mat == Y.mat; }

        inline bool operator!=(const Matrix Y) const { return mat != Y.mat; }

        inline vector<T>&operator[](int i) { return mat[i] ; }

        Matrix(int n): row(n), col(0) { mat.resize(row); }
        Matrix(vector<T> A, bool row_matrix = false) { init_(A, row_matrix); }
        Matrix(vector<vector<T>> A){ init_(A); }
        void init(vector<T> A, bool row_matrix = false) { init_(A, row_matrix); }
        void init(vector<vector<T>> A) { init_(A); }
        size_t row_size() { return row; }
        size_t col_size() { return col; }
        Matrix pow(ll k){ return pow_(k); }
        void transpose() { transpose_(); }
        void concat_col(vector<vector<T>> &Y) { concat_col_(Y); }
        void concat_col(vector<T> &Y) { concat_col_(Y); }
        void concat_col(Matrix &Y) { concat_col_(Y); }
        void concat_row(vector<vector<T>> &Y) { concat_row_(Y); }
        void concat_row(vector<T> &Y) { concat_row_(Y); }
        void concat_row(Matrix &Y) { concat_row_(Y); }
        void print() { print_(); }
};

// 誤差
template<typename T> struct GaussJordan{

    const double EPS = 1e-10 ;

    private:

        int rank;
        vector<T> solution;

        // 階数（Rank）を返す  (注意 : 参照渡しのためmatrixも変化する)
        // mat : 行列 , is_extended : 拡大係数行列かどうか
        int sweep_out_(Matrix<T> &mat, bool is_extended){

            // 行列の条件
            int n = mat.row , m = mat.col;
            // 階数
            rank = 0 ;

            for(int col = 0 ; col < m ; col++){
                // 拡大係数行列の場合、最後の列は何もしない
                if(is_extended && col == m - 1) break ;

                // ピボットを探す
                int pivot = -1 ;
                T e = EPS ;
                for(int row = rank ; row < n ; row++){
                    if(abs(mat[row][col]) > e){
                        e = abs(mat[row][col]) ;
                        pivot = row ;
                    }
                }

                // ピボットがなかったら次の列へ
                if(pivot == -1) continue ;

                // 行をスワップする
                swap(mat[rank] , mat[pivot]) ;

                // ピボットの値を1にする（このあとの演算のため）
                auto fac = mat[rank][col] ;
                for(int col2 = 0 ; col2 < m ; col2++) mat[rank][col2] /= fac ;

                // 今見ている列を掃き出す
                for(int row = 0 ; row < n ; row++){
                    // 見てる行が基準の行でない && 値が1e-10より大きい
                    if(row != rank && abs(mat[row][col]) > EPS){
                        // 列基本操作
                        auto fac = mat[row][col] ;
                        for(int col2 = 0 ; col2 < m ; col2++){
                            mat[row][col2] -= mat[rank][col2] * fac ;
                        }
                    }
                }
                rank++ ;
            }
            return rank ;
        }

        vector<T> solve_simultaneous_equation_(vector<vector<T>> &A , vector<T> &b){
            return solve_simultaneous_equation_(Matrix<T>(A), Matrix<T>(b));
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &A , vector<T> &b){
            return solve_simultaneous_equation_(A, Matrix<T>(b));
        }
        vector<T> solve_simultaneous_equation_(vector<vector<T>> &A , Matrix<T> &b){
            return solve_simultaneous_equation_(Matrix<T>(A), b);
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &A , Matrix<T> &b){
            return solve_simultaneous_equation_(A.concat_col(b));
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &M){
            int n = M.row, m = M.col;
            int rank = sweep_out(M,true);

            // 解があるかの確認（行列の階数より上の領域で解があるとおかしい）
            for(int row = rank ; row < n ; row++) if(abs(M[row][m]) > EPS) return {};

            // 答え
            vector<T> res(rank,0) ;
            for(int i = 0 ; i < rank ; i++) res[i] = M[i][m-1] ;

            return solution = res;
        }

    public:
        GaussJordan(){}
        int sweep_out(Matrix<T> &A) { return sweep_out_(A, false); }
        int sweep_out(Matrix<T> &A, bool is_extended) { return sweep_out_(A, is_extended); }
        vector<T> solve_simultaneous_equation(Matrix<T> &A , Matrix<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(Matrix<T> &A , vector<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(vector<vector<T>> &A , vector<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(vector<vector<T>> &A , Matrix<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(Matrix<T> A) { return solve_simultaneous_equation_(A); }
        int get_rank() { return rank; }
        vector<T> get_solution() { return solution; }
};

int n, s, t;

struct edge{
    int to ;
    ll cost ;
};

vector<vector<edge>> G;
vector<vector<edge>> F;
ll d[202] ;
int A[202];
int prevv[202] ; // 一個前のノード
vector<int> line ; // 経路復元

// 始点: s , 終点: t
void djikstra(int s){
    rep(i,n) d[i] = 1e16 ;
    rep(i,n) prevv[i] = -1 ;
    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 dist = p.first;
        int v = p.second;
        if(d[v] < dist) continue;
        for(int i = 0 ; i < G[v].size() ; i++){
            edge e = G[v][i] ;
            if(d[e.to] > d[v] + e.cost){
                d[e.to] = d[v] + e.cost ;
                prevv[e.to] = v ;
                que.push(P(d[e.to],e.to)) ;
            }
        }
    }
}

int main(){
    // fast_io
    while(true){
        F.clear();
        G.clear();
        cin >> n >> s >> t;
        G.resize(n);
        F.resize(n);
        if(n == 0 && s == 0 && t == 0) break;
        s--; t--;
        rep(i,n) cin >> A[i];
        rep(i,n) rep(j,n){
            int a;
            cin >> a;
            if(a == 0) continue;
            G[i].push_back({j,a});
        }
        djikstra(t);
        if(d[s] == 1e16){
            cout << "impossible" << endl;
            return 0;
        }
        rep(i,n){
            int minval = 1e9;
            vector<edge> vec;
            for(edge e : G[i]){
                int u = e.to;
                if(minval > d[u] + e.cost){
                    minval = d[u] + e.cost;
                    vec = {};
                    vec.push_back({u, e.cost});
                }
                else if(minval == d[u] + e.cost){
                    vec.push_back({u, e.cost});
                }
            }
            F[i] = vec;
        }
        vector<vector<ld>> mat(n,vector<ld>(n+1,0));
        rep(i,n){
            if(i == t){
                mat[i][i] = 1;
                continue;
            }
            if(A[i]){
                int m = F[i].size();
                ld w = 0;
                mat[i][i] = m;
                for(edge e : F[i]){
                    mat[i][e.to] = -1;
                    w += e.cost;
                }
                mat[i][n] = w;
            }
            else{
                int m = G[i].size();
                ld w = 0;
                mat[i][i] = m;
                for(edge e :G[i]){
                    mat[i][e.to] = -1;
                    w += e.cost;
                }
                mat[i][n] = w;
            }
        }
        GaussJordan<ld> gj;
        vector<ld> res = gj.solve_simultaneous_equation(Matrix<ld>(mat));
        cout << fixed << setprecision(25) << res[s] << endl;
    }
}
accuracy: 1
time_ms: 30
memory_kb: 4164
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std ;
#define fast_io ios::sync_with_stdio(false); cin.tie(nullptr);
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
typedef long long ll ;
typedef long double ld ;
typedef pair<ll,ll> P ;
typedef tuple<ll,ll,ll> TP ;
#define chmin(a,b) a = min(a,b)
#define chmax(a,b) a = max(a,b)
#define bit_count(x) __builtin_popcountll(x)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a / gcd(a,b) * b
#define rep(i,n) for(int i = 0 ; i < n ; i++)
#define rrep(i,a,b) for(int i = a ; i < b ; i++)
#define repi(it,S) for(auto it = S.begin() ; it != S.end() ; it++)
#define pt(a) cout << a << endl
#define DEBUG(...) ; cout << #__VA_ARGS__ << endl ; for(auto x : {__VA_ARGS__}) cout << x << "  " ; cout << endl ;
#define DEBUG_LIST(...) cout << #__VA_ARGS__ << endl ; DEBUG_REP(__VA_ARGS__) ;
#define DEBUG_REP(V) cout << "{ " ; repi(itr,V) cout << *itr << ", " ; cout << "}" << endl ;
#define debug(a) cout << #a << " " << a << endl
#define all(a) a.begin(), a.end()
#define endl "\n"


template<typename T = ll> struct Matrix{
    int row, col;
    vector<vector<T>> mat ;

    private:
        void init_(vector<vector<T>> A){
            row = A.size();
            col = A[0].size();
            mat = A;
        }
        
        void init_(vector<T> A, bool row_matrix = false){
            if(row_matrix) {
                col = (int)A.size();
                row = 1;
                mat.resize(1);
                mat[0] = A;
            }
            else {
                col = 1;
                row = (int)A.size();
                mat.resize(row,vector<T>(1));
                rep(i,row) mat[i][0] = A[i];
            }
        }

        Matrix<T> pow_(ll k){
            assert(row == col);
            vector<vector<T>> E(row,vector<T>(row,0));
            rep(i,row) rep(j,row) if(i == j) E[i][j] = 1;
            Matrix<T> res(E);
            Matrix<T> X(mat);
            while(k > 0){
                if(k & 1) res *= X;
                X *= X;
                k >>= 1 ;
            }
            return res;
        }

        void transpose_() {
            vector<vector<T>> res(col,vector<T>(row));
            rep(i,row) rep(j,col) res[j][i] = mat[i][j];
            swap(row,col);
            mat = res;
        }

        void concat_col_(vector<T> &Y) {
            Matrix X(Y);
            concat_col_(X);
        }
        void concat_col_(vector<vector<T>> &Y) {
            Matrix X(Y);
            concat_col_(X);
        }
        void concat_col_(Matrix &Y) {
            assert((int)Y.row == row);
            col += Y.col;
            rep(i,row) {
                rep(j,Y.col) mat[i].push_back(Y.mat[i][j]);
            }
        }

        void concat_row_(vector<T> &Y) {
            Matrix X(Y,true);
            concat_row_(X);
        }
        void concat_row_(vector<vector<T>> &Y) {
            Matrix X(Y);
            concat_row_(X);
        }
        void concat_row_(Matrix &Y) {
            assert((int)Y.col == col);
            row += Y.row;
            rep(i,Y.row) mat.push_back(Y.mat[i]);
        }

        void print_() {
            rep(i,row){
                rep(j,col) cout << mat[i][j] << " "; cout << endl;
            }
        }

    public:

        inline Matrix &operator+=(const Matrix Y) {
            rep(i,row) rep(j,col) mat[i][j] += Y.mat[i][j];
            return *this ;
        }

        inline Matrix &operator-=(const Matrix Y) {
            rep(i,row) rep(j,col) mat[i][j] -= Y.mat[i][j];
            return *this ;
        }

        inline Matrix &operator*=(const Matrix Y) {
            int x = row, y = Y.col, n = col;
            vector<vector<T>> res(x,vector<T>(y));
            rep(i,x) rep(j,y) rep(k,n) res[i][j] += mat[i][k] * Y.mat[k][j];
            swap(mat,res);
            return *this ;
        }

        inline Matrix operator-() const {
            rep(i,row) rep(j,col) mat[i][j] *= -1;
            return *this ;
        }

        inline Matrix operator+(const Matrix Y) const { return Matrix(*this) += Y; }

        inline Matrix operator-(const Matrix Y) const { return Matrix(*this) -= Y; }

        inline Matrix operator*(const Matrix Y) const { return Matrix(*this) *= Y; }

        inline bool operator==(const Matrix Y) const { return mat == Y.mat; }

        inline bool operator!=(const Matrix Y) const { return mat != Y.mat; }

        inline vector<T>&operator[](int i) { return mat[i] ; }

        Matrix(int n): row(n), col(0) { mat.resize(row); }
        Matrix(vector<T> A, bool row_matrix = false) { init_(A, row_matrix); }
        Matrix(vector<vector<T>> A){ init_(A); }
        void init(vector<T> A, bool row_matrix = false) { init_(A, row_matrix); }
        void init(vector<vector<T>> A) { init_(A); }
        size_t row_size() { return row; }
        size_t col_size() { return col; }
        Matrix pow(ll k){ return pow_(k); }
        void transpose() { transpose_(); }
        void concat_col(vector<vector<T>> &Y) { concat_col_(Y); }
        void concat_col(vector<T> &Y) { concat_col_(Y); }
        void concat_col(Matrix &Y) { concat_col_(Y); }
        void concat_row(vector<vector<T>> &Y) { concat_row_(Y); }
        void concat_row(vector<T> &Y) { concat_row_(Y); }
        void concat_row(Matrix &Y) { concat_row_(Y); }
        void print() { print_(); }
};

// 誤差
template<typename T> struct GaussJordan{

    const double EPS = 1e-10 ;

    private:

        int rank;
        vector<T> solution;

        // 階数（Rank）を返す  (注意 : 参照渡しのためmatrixも変化する)
        // mat : 行列 , is_extended : 拡大係数行列かどうか
        int sweep_out_(Matrix<T> &mat, bool is_extended){

            // 行列の条件
            int n = mat.row , m = mat.col;
            // 階数
            rank = 0 ;

            for(int col = 0 ; col < m ; col++){
                // 拡大係数行列の場合、最後の列は何もしない
                if(is_extended && col == m - 1) break ;

                // ピボットを探す
                int pivot = -1 ;
                T e = EPS ;
                for(int row = rank ; row < n ; row++){
                    if(abs(mat[row][col]) > e){
                        e = abs(mat[row][col]) ;
                        pivot = row ;
                    }
                }

                // ピボットがなかったら次の列へ
                if(pivot == -1) continue ;

                // 行をスワップする
                swap(mat[rank] , mat[pivot]) ;

                // ピボットの値を1にする（このあとの演算のため）
                auto fac = mat[rank][col] ;
                for(int col2 = 0 ; col2 < m ; col2++) mat[rank][col2] /= fac ;

                // 今見ている列を掃き出す
                for(int row = 0 ; row < n ; row++){
                    // 見てる行が基準の行でない && 値が1e-10より大きい
                    if(row != rank && abs(mat[row][col]) > EPS){
                        // 列基本操作
                        auto fac = mat[row][col] ;
                        for(int col2 = 0 ; col2 < m ; col2++){
                            mat[row][col2] -= mat[rank][col2] * fac ;
                        }
                    }
                }
                rank++ ;
            }
            return rank ;
        }

        vector<T> solve_simultaneous_equation_(vector<vector<T>> &A , vector<T> &b){
            return solve_simultaneous_equation_(Matrix<T>(A), Matrix<T>(b));
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &A , vector<T> &b){
            return solve_simultaneous_equation_(A, Matrix<T>(b));
        }
        vector<T> solve_simultaneous_equation_(vector<vector<T>> &A , Matrix<T> &b){
            return solve_simultaneous_equation_(Matrix<T>(A), b);
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &A , Matrix<T> &b){
            return solve_simultaneous_equation_(A.concat_col(b));
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &M){
            int n = M.row;
            int rank = sweep_out(M,true);

            // 解があるかの確認（行列の階数より上の領域で解があるとおかしい）
            vector<T> res ;
            for(int row = rank ; row < n ; row++) if(abs(M[row][n]) > EPS) return res ;

            // 答え
            res.assign(n,0) ;
            for(int i = 0 ; i < rank ; i++) res[i] = M[i][n] ;
            solution = res;
            return res ;
        }

    public:
        GaussJordan(){}
        int sweep_out(Matrix<T> &A, bool is_extended = false) { return sweep_out_(A, is_extended); }
        vector<T> solve_simultaneous_equation(Matrix<T> &A , Matrix<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(Matrix<T> &A , vector<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(vector<vector<T>> &A , vector<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(vector<vector<T>> &A , Matrix<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(Matrix<T> A) { return solve_simultaneous_equation_(A); }
        int get_rank() { return rank; }
        vector<T> get_solution() { return solution; }
};

int n, s, t;

struct edge{
    int to ;
    ll cost ;
};

vector<vector<edge>> G;
vector<vector<edge>> F;
ll d[202] ;
int A[202];
int prevv[202] ; // 一個前のノード
vector<int> line ; // 経路復元

// 始点: s , 終点: t
void djikstra(int s){
    rep(i,n) d[i] = 1e16 ;
    rep(i,n) prevv[i] = -1 ;
    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 dist = p.first;
        int v = p.second;
        if(d[v] < dist) continue;
        for(int i = 0 ; i < G[v].size() ; i++){
            edge e = G[v][i] ;
            if(d[e.to] > d[v] + e.cost){
                d[e.to] = d[v] + e.cost ;
                prevv[e.to] = v ;
                que.push(P(d[e.to],e.to)) ;
            }
        }
    }
}

int main(){
    // fast_io
    while(true){
        F.clear();
        G.clear();
        cin >> n >> s >> t;
        G.resize(n);
        F.resize(n);
        if(n == 0 && s == 0 && t == 0) break;
        s--; t--;
        rep(i,n) cin >> A[i];
        rep(i,n) rep(j,n){
            int a;
            cin >> a;
            if(a == 0) continue;
            G[i].push_back({j,a});
        }
        djikstra(t);
        if(d[s] == 1e16){
            cout << "impossible" << endl;
            return 0;
        }
        rep(i,n){
            int minval = 1e9;
            vector<edge> vec;
            for(edge e : G[i]){
                int u = e.to;
                if(minval > d[u] + e.cost){
                    minval = d[u] + e.cost;
                    vec = {};
                    vec.push_back({u, e.cost});
                }
                else if(minval == d[u] + e.cost){
                    vec.push_back({u, e.cost});
                }
            }
            F[i] = vec;
        }
        vector<vector<ld>> mat(n,vector<ld>(n+1,0));
        rep(i,n){
            if(i == t){
                mat[i][i] = 1;
                continue;
            }
            if(A[i]){
                int m = F[i].size();
                ld w = 0;
                mat[i][i] = m;
                for(edge e : F[i]){
                    mat[i][e.to] = -1;
                    w += e.cost;
                }
                mat[i][n] = w;
            }
            else{
                int m = G[i].size();
                ld w = 0;
                mat[i][i] = m;
                for(edge e :G[i]){
                    mat[i][e.to] = -1;
                    w += e.cost;
                }
                mat[i][n] = w;
            }
        }
        GaussJordan<ld> gj;
        vector<ld> res = gj.solve_simultaneous_equation(Matrix<ld>(mat));
        cout << fixed << setprecision(25) << res[s] << endl;
    }
}
accuracy: 1
time_ms: 30
memory_kb: 4128
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std ;
#define fast_io ios::sync_with_stdio(false); cin.tie(nullptr);
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
typedef long long ll ;
typedef long double ld ;
typedef pair<ll,ll> P ;
typedef tuple<ll,ll,ll> TP ;
#define chmin(a,b) a = min(a,b)
#define chmax(a,b) a = max(a,b)
#define bit_count(x) __builtin_popcountll(x)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a / gcd(a,b) * b
#define rep(i,n) for(int i = 0 ; i < n ; i++)
#define rrep(i,a,b) for(int i = a ; i < b ; i++)
#define repi(it,S) for(auto it = S.begin() ; it != S.end() ; it++)
#define pt(a) cout << a << endl
#define DEBUG(...) ; cout << #__VA_ARGS__ << endl ; for(auto x : {__VA_ARGS__}) cout << x << "  " ; cout << endl ;
#define DEBUG_LIST(...) cout << #__VA_ARGS__ << endl ; DEBUG_REP(__VA_ARGS__) ;
#define DEBUG_REP(V) cout << "{ " ; repi(itr,V) cout << *itr << ", " ; cout << "}" << endl ;
#define debug(a) cout << #a << " " << a << endl
#define all(a) a.begin(), a.end()
#define endl "\n"


template<typename T = ll> struct Matrix{
    int row, col;
    vector<vector<T>> mat ;

    private:
        void init_(vector<vector<T>> A){
            row = A.size();
            col = A[0].size();
            mat = A;
        }
        
        void init_(vector<T> A, bool row_matrix = false){
            if(row_matrix) {
                col = (int)A.size();
                row = 1;
                mat.resize(1);
                mat[0] = A;
            }
            else {
                col = 1;
                row = (int)A.size();
                mat.resize(row,vector<T>(1));
                rep(i,row) mat[i][0] = A[i];
            }
        }

        Matrix<T> pow_(ll k){
            assert(row == col);
            vector<vector<T>> E(row,vector<T>(row,0));
            rep(i,row) rep(j,row) if(i == j) E[i][j] = 1;
            Matrix<T> res(E);
            Matrix<T> X(mat);
            while(k > 0){
                if(k & 1) res *= X;
                X *= X;
                k >>= 1 ;
            }
            return res;
        }

        Matrix transpose_() {
            vector<vector<T>> res(col,vector<T>(row));
            rep(i,row) rep(j,col) res[j][i] = mat[i][j];
            swap(row,col);
            return mat = res;
        }

        Matrix concat_col_(vector<T> &Y) {
            Matrix X(Y);
            return concat_col_(X);
        }
        Matrix concat_col_(vector<vector<T>> &Y) {
            Matrix X(Y);
            return concat_col_(X);
        }
        Matrix concat_col_(Matrix &Y) {
            assert((int)Y.row == row);
            col += Y.col;
            rep(i,row) {
                rep(j,Y.col) mat[i].push_back(Y.mat[i][j]);
            }
            return mat;
        }

        Matrix concat_row_(vector<T> &Y) {
            Matrix X(Y,true);
            return concat_row_(X);
        }
        Matrix concat_row_(vector<vector<T>> &Y) {
            Matrix X(Y);
            return concat_row_(X);
        }
        Matrix concat_row_(Matrix &Y) {
            assert((int)Y.col == col);
            row += Y.row;
            rep(i,Y.row) mat.push_back(Y.mat[i]);
            return mat;
        }

        void print_() {
            rep(i,row){
                rep(j,col) cout << mat[i][j] << " "; cout << endl;
            }
        }

    public:

        inline Matrix &operator+=(const Matrix Y) {
            rep(i,row) rep(j,col) mat[i][j] += Y.mat[i][j];
            return *this ;
        }

        inline Matrix &operator-=(const Matrix Y) {
            rep(i,row) rep(j,col) mat[i][j] -= Y.mat[i][j];
            return *this ;
        }

        inline Matrix &operator*=(const Matrix Y) {
            int x = row, y = Y.col, n = col;
            vector<vector<T>> res(x,vector<T>(y));
            rep(i,x) rep(j,y) rep(k,n) res[i][j] += mat[i][k] * Y.mat[k][j];
            swap(mat,res);
            return *this ;
        }

        inline Matrix operator-() const {
            rep(i,row) rep(j,col) mat[i][j] *= -1;
            return *this ;
        }

        inline Matrix operator+(const Matrix Y) const { return Matrix(*this) += Y; }

        inline Matrix operator-(const Matrix Y) const { return Matrix(*this) -= Y; }

        inline Matrix operator*(const Matrix Y) const { return Matrix(*this) *= Y; }

        inline bool operator==(const Matrix Y) const { return mat == Y.mat; }

        inline bool operator!=(const Matrix Y) const { return mat != Y.mat; }

        inline vector<T>&operator[](int i) { return mat[i] ; }

        Matrix(int n): row(n), col(0) { mat.resize(row); }
        Matrix(vector<T> A, bool row_matrix = false) { init_(A, row_matrix); }
        Matrix(vector<vector<T>> A){ init_(A); }
        void init(vector<T> A, bool row_matrix = false) { init_(A, row_matrix); }
        void init(vector<vector<T>> A) { init_(A); }
        size_t row_size() { return row; }
        size_t col_size() { return col; }
        Matrix pow(ll k){ return pow_(k); }
        Matrix transpose() { return transpose_(); }
        Matrix concat_col(vector<vector<T>> &Y) { return concat_col_(Y); }
        Matrix concat_col(vector<T> &Y) { return concat_col_(Y); }
        Matrix concat_col(Matrix &Y) { return concat_col_(Y); }
        Matrix concat_row(vector<vector<T>> &Y) { return concat_row_(Y); }
        Matrix concat_row(vector<T> &Y) { return concat_row_(Y); }
        Matrix concat_row(Matrix &Y) { return concat_row_(Y); }
        void print() { print_(); }
};

// 誤差
template<typename T> struct GaussJordan{

    const double EPS = 1e-10 ;

    private:

        int rank;
        vector<T> solution;

        // 階数（Rank）を返す  (注意 : 参照渡しのためmatrixも変化する)
        // mat : 行列 , is_extended : 拡大係数行列かどうか
        int sweep_out_(Matrix<T> &mat, bool is_extended){

            // 行列の条件
            int n = mat.row , m = mat.col;
            // 階数
            rank = 0 ;

            for(int col = 0 ; col < m ; col++){
                // 拡大係数行列の場合、最後の列は何もしない
                if(is_extended && col == m - 1) break ;

                // ピボットを探す
                int pivot = -1 ;
                T e = EPS ;
                for(int row = rank ; row < n ; row++){
                    if(abs(mat[row][col]) > e){
                        e = abs(mat[row][col]) ;
                        pivot = row ;
                    }
                }

                // ピボットがなかったら次の列へ
                if(pivot == -1) continue ;

                // 行をスワップする
                swap(mat[rank] , mat[pivot]) ;

                // ピボットの値を1にする（このあとの演算のため）
                auto fac = mat[rank][col] ;
                for(int col2 = 0 ; col2 < m ; col2++) mat[rank][col2] /= fac ;

                // 今見ている列を掃き出す
                for(int row = 0 ; row < n ; row++){
                    // 見てる行が基準の行でない && 値が1e-10より大きい
                    if(row != rank && abs(mat[row][col]) > EPS){
                        // 列基本操作
                        auto fac = mat[row][col] ;
                        for(int col2 = 0 ; col2 < m ; col2++){
                            mat[row][col2] -= mat[rank][col2] * fac ;
                        }
                    }
                }
                rank++ ;
            }
            return rank ;
        }

        vector<T> solve_simultaneous_equation_(vector<vector<T>> &A , vector<T> &b){
            return solve_simultaneous_equation_(Matrix<T>(A), Matrix<T>(b));
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &A , vector<T> &b){
            return solve_simultaneous_equation_(A, Matrix<T>(b));
        }
        vector<T> solve_simultaneous_equation_(vector<vector<T>> &A , Matrix<T> &b){
            return solve_simultaneous_equation_(Matrix<T>(A), b);
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &A , Matrix<T> &b){
            return solve_simultaneous_equation_(A.concat_col(b));
        }
        vector<T> solve_simultaneous_equation_(Matrix<T> &M){
            int n = M.row;
            int rank = sweep_out(M,true);

            // 解があるかの確認（行列の階数より上の領域で解があるとおかしい）
            vector<T> res ;
            for(int row = rank ; row < n ; row++) if(abs(M[row][n]) > EPS) return res ;

            // 答え
            res.assign(n,0) ;
            for(int i = 0 ; i < rank ; i++) res[i] = M[i][n] ;
            solution = res;
            return res ;
        }

    public:
        GaussJordan(){}
        int sweep_out(Matrix<T> &A, bool is_extended = false) { return sweep_out_(A, is_extended); }
        vector<T> solve_simultaneous_equation(Matrix<T> &A , Matrix<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(Matrix<T> &A , vector<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(vector<vector<T>> &A , vector<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(vector<vector<T>> &A , Matrix<T> &b) { return solve_simultaneous_equation_(A, b); }
        vector<T> solve_simultaneous_equation(Matrix<T> A) { return solve_simultaneous_equation_(A); }
        int get_rank() { return rank; }
        vector<T> get_solution() { return solution; }
};

int n, s, t;

struct edge{
    int to ;
    ll cost ;
};

vector<vector<edge>> G;
vector<vector<edge>> F;
ll d[202] ;
int A[202];
int prevv[202] ; // 一個前のノード
vector<int> line ; // 経路復元

// 始点: s , 終点: t
void djikstra(int s){
    rep(i,n) d[i] = 1e16 ;
    rep(i,n) prevv[i] = -1 ;
    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 dist = p.first;
        int v = p.second;
        if(d[v] < dist) continue;
        for(int i = 0 ; i < G[v].size() ; i++){
            edge e = G[v][i] ;
            if(d[e.to] > d[v] + e.cost){
                d[e.to] = d[v] + e.cost ;
                prevv[e.to] = v ;
                que.push(P(d[e.to],e.to)) ;
            }
        }
    }
}

int main(){
    // fast_io
    while(true){
        F.clear();
        G.clear();
        cin >> n >> s >> t;
        G.resize(n);
        F.resize(n);
        if(n == 0 && s == 0 && t == 0) break;
        s--; t--;
        rep(i,n) cin >> A[i];
        rep(i,n) rep(j,n){
            int a;
            cin >> a;
            if(a == 0) continue;
            G[i].push_back({j,a});
        }
        djikstra(t);
        if(d[s] == 1e16){
            cout << "impossible" << endl;
            return 0;
        }
        rep(i,n){
            int minval = 1e9;
            vector<edge> vec;
            for(edge e : G[i]){
                int u = e.to;
                if(minval > d[u] + e.cost){
                    minval = d[u] + e.cost;
                    vec = {};
                    vec.push_back({u, e.cost});
                }
                else if(minval == d[u] + e.cost){
                    vec.push_back({u, e.cost});
                }
            }
            F[i] = vec;
        }
        vector<vector<ld>> mat(n,vector<ld>(n+1,0));
        rep(i,n){
            if(i == t){
                mat[i][i] = 1;
                continue;
            }
            if(A[i]){
                int m = F[i].size();
                ld w = 0;
                mat[i][i] = m;
                for(edge e : F[i]){
                    mat[i][e.to] = -1;
                    w += e.cost;
                }
                mat[i][n] = w;
            }
            else{
                int m = G[i].size();
                ld w = 0;
                mat[i][i] = m;
                for(edge e :G[i]){
                    mat[i][e.to] = -1;
                    w += e.cost;
                }
                mat[i][n] = w;
            }
        }
        GaussJordan<ld> gj;
        vector<ld> res = gj.solve_simultaneous_equation(Matrix<ld>(mat));
        cout << fixed << setprecision(25) << res[s] << endl;
    }
}
accuracy: 1
time_ms: 30
memory_kb: 4224
final_rank: 18

code_snippet: #include <iostream>
#include <vector>
using namespace std;

// Input
int N, S, T;
int Q[109];
int A[109][109];

// Others
int dist[109][109];
double Expc[28][109][109];
double Prob[28][109][109];

void solve() {
	// Warshall-Floyd
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			if (A[i][j] == 0) dist[i][j] = 100000;
			else dist[i][j] = A[i][j];
		}
		dist[i][i] = 0;
	}
	for (int k = 1; k <= N; k++) {
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
		}
	}
	
	// Corner Case
	if (dist[S][T] == 100000) {
		cout << "impossible" << endl;
		return;
	}
	
	// Get Probability
	for (int d = 0; d <= 25; d++) {
		for (int i = 1; i <= N+1; i++) {
			for (int j = 1; j <= N+1; j++) Prob[d][i][j] = 0.0;
			for (int j = 1; j <= N+1; j++) Expc[d][i][j] = 0.0;
		}
	}
	for (int i = 1; i <= N; i++) {
		if (i == T) {
			Prob[0][i][N+1] = 1.0;
			Expc[0][i][N+1] = 0.0;
		}
		else {
			vector<int> vec;
			for (int j = 1; j <= N; j++) {
				if (Q[i] == 0 && A[i][j] != 0) vec.push_back(j);
				if (Q[i] == 1 && A[i][j] != 0 && A[i][j] + dist[j][T] == dist[i][T]) vec.push_back(j);
			}
			if (vec.size() == 0) continue;
			for (int j : vec) {
				Prob[0][i][j] = 1.0 / (double)vec.size();
				Expc[0][i][j] = 1.0 * A[i][j];
				//cout << i << " " << j << endl;
			}
		}
	}
	Prob[0][N+1][N+1] = 1.0;
	Expc[0][N+1][N+1] = 0.0;
	
	// Matrix Operations
	for (int d = 0; d < 25; d++) {
		for (int i = 1; i <= N+1; i++) {
			for (int k = 1; k <= N+1; k++) {
				for (int j = 1; j <= N+1; j++) {
					double prob = Prob[d][i][k] * Prob[d][k][j];
					Prob[d+1][i][j] += prob;
					Expc[d+1][i][j] += (Expc[d][i][k] + Expc[d][k][j]) * prob;
				}
			}
		}
		for (int i = 1; i <= N+1; i++) {
			for (int j = 1; j <= N+1; j++) {
				if (Prob[d+1][i][j] != 0) Expc[d+1][i][j] /= Prob[d+1][i][j];
			}
		}
	}
	
	// Output
	printf("%.12lf\n", Expc[25][S][N+1]);
}

int main() {
	while (true) {
		// Input
		cin >> N >> S >> T;
		if (N == 0 && S == 0 && T == 0) break;
		for (int i = 1; i <= N; i++) cin >> Q[i];
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) cin >> A[i][j];
		}
		
		// Solve
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 8328
final_rank: 20

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

constexpr int INF = 1 << 30;
constexpr double EPS = 1e-8;

int gaussian(vector<vector<double>>& a, int last) {
    int h = a.size(), w = a[0].size();
    int rank = 0;
    for (int j = 0; j < w - last; j++) {
        int pivot = -1;
        for (int i = rank; i < h; i++) {
            if (abs(a[i][j]) > EPS) {
                pivot = i;
                break;
            }
        }
        if (pivot == -1) continue;
        if (rank != pivot) swap(a[rank], a[pivot]);
        for (int k = w - 1; k >= j; k--) a[rank][k] /= a[rank][j];
        for (int i = 0; i < h; i++) {
            if (i == rank) continue;
            for (int k = w - 1; k >= j; k--) a[i][k] -= a[rank][k] * a[i][j];
        }
        rank++;
    }
    return rank;
}

vector<double> linear(vector<vector<double>>& a, const vector<double>& b) {
    int h = a.size(), w = a[0].size();
    for (int i = 0; i < h; i++) a[i].emplace_back(b[i]);
    int rank = gaussian(a, 1);
    for (int i = rank; i < h; i++) {
        if (abs(a[i][w]) > EPS) {
            return vector<double>();
        }
    }
    vector<double> res(w);
    for (int i = 0, j = 0; i < rank and j < w; i++) {
        while (abs(a[i][j]) < EPS) j++;
        res[j] = a[i][w];
    }
    return res;
}

void solve(int n, int s, int t) {
    s--, t--;
    vector<int> q(n);
    for (int i = 0; i < n; i++) cin >> q[i];
    vector<vector<int>> a(n, vector<int>(n));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> a[i][j];
        }
    }

    vector<int> dist(n, INF);
    priority_queue<pair<int, int>> pq;
    dist[t] = 0;
    pq.emplace(-dist[t], t);
    while (!pq.empty()) {
        auto p = pq.top();
        pq.pop();
        auto [cost, v] = p;
        cost *= -1;
        if (dist[v] < cost) continue;
        for (int u = 0; u < n; u++) {
            if (a[v][u] == 0) continue;
            if (cost + a[v][u] < dist[u]) {
                dist[u] = cost + a[v][u];
                pq.emplace(-dist[u], u);
            }
        }
    }
    if (dist[s] == INF) {
        cout << "impossible" << '\n';
        return;
    }

    vector<vector<double>> mat(n + 1, vector<double>(n + 1, 0));
    vector<double> b(n + 1, 0);
    for (int i = 0; i < n; i++) {
        if (dist[i] == INF) {
            mat[i][i] = 1;
            b[i] = 1;
            continue;
        }
        if (i == t) {
            mat[i][i] = 1;
            b[i] = 0;
            continue;
        }
        int route = 0, sum = 0;
        for (int j = 0; j < n; j++) {
            if (a[i][j] == 0) continue;
            if (q[i] and dist[i] != dist[j] + a[j][i]) continue;
            route++;
            sum += a[i][j];
        }
        double inv = 1.0 / route;
        mat[i][i] = -1;
        mat[i][n] = inv * sum;
        for (int j = 0; j < n; j++) {
            if (a[i][j] == 0) continue;
            if (q[i] and dist[i] != dist[j] + a[j][i]) continue;
            mat[i][j] += inv;
        }
    }
    mat[n][n] = 1;
    b[n] = 1;

    auto res = linear(mat, b);
    assert(not res.empty());
    double ans = res[s];
    cout << ans << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    for (int n, s, t; cin >> n >> s >> t, n;) solve(n, s, t);
}
accuracy: 1
time_ms: 10
memory_kb: 3860
final_rank: 5