#include <iostream>
#include <iomanip>
#include <cstring>
#include <queue>
#include <vector>
#include <string>
#include <map>
#include <algorithm>

#define REP(i,n) for(int i=0;i<(int)(n);i++)

using namespace std;

typedef long double Data;
typedef vector<Data> Array;
typedef vector<Array> Matrix;

pair<Matrix, vector<int>> LUPDecomposition(Matrix A) {
  int n=A.size();
  vector<int> perm(n);
  iota(begin(perm),end(perm),0);
  REP(i,n){
    int pivot = i;
    for(int j = i+1; j < n; ++j)
      if(abs(A[j][i]) > abs(A[pivot][i])) pivot = j;
    swap(A[pivot], A[i]);
    swap(perm[pivot], perm[i]);
    for(int j=i+1; j < n; ++j) {
      A[j][i] /= A[i][i];
      for (int k = i+1; k < n; ++k)
        A[j][k] -= A[i][k] * A[j][i];
    }
  }
  return make_pair(A, perm);
}

Array LUPBackSubstitution(Matrix& LU, vector<int>& perm, Array a) {
  int n=LU.size();
  Array tmp(n);
  REP(i,n)
    tmp[i] = a[perm[i]];
  swap(tmp, a);
  REP(i,n)
    REP(j,i) a[i] -= a[j] * LU[i][j];
  for(int i=n-1; i >= 0; --i) {
    for(int j=i+1; j < n; ++j)
      a[i] -= a[j] * LU[i][j];
    a[i] /= LU[i][i];
  }
  return a;
}
#define MAX_V 10000
int V;

typedef long double ld;
typedef ld Weight;
const Weight INF = 1000000000;
const Weight eps = 1e-6;

struct Edge{
  int src, dest;
  int cap, rev;
  Weight weight;
  bool operator < (const Edge &rhs) const {return weight > rhs.weight;}
};

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

Weight h[MAX_V];                // potential
Weight dist[MAX_V];             // minimum distance
int prevv[MAX_V], preve[MAX_V]; // previous vertex and edge

void add_edge(Graph &g, int src, int dest, int cap, Weight weight) {
  g[src].push_back((Edge){src, dest, cap, (int)g[dest].size(), weight});
  g[dest].push_back((Edge){dest, src, 0, (int)g[src].size() - 1, -weight});
}

Weight min_cost_flow(Graph &g, int s, int t, int f) {
  Weight res = 0; V = g.size();
  REP(i,MAX_V)h[i]=0;
  typedef pair<Weight, int> P;
  while (f > 0) {
    priority_queue<P, vector<P>, greater<P> > que;
    fill(dist, dist + V, INF);
    dist[s] = 0;
    que.push(P(0, s));
    while (!que.empty()) {
      P p = que.top(); que.pop();
      int v = p.second; 
      if (dist[v] < p.first) continue;
      REP(i, g[v].size()) {
        Edge &e = g[v][i];
        if (e.cap > 0 && dist[e.dest] > dist[v] + e.weight + h[v] - h[e.dest] + eps) {
          dist[e.dest] = dist[v] + e.weight + h[v] - h[e.dest];
          prevv[e.dest] = v;
          preve[e.dest] = i;
          que.push(P(dist[e.dest], e.dest));
        }
      }
    }
    if (dist[t] == INF) return -1;
    REP(v, V) h[v] += dist[v];

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

int main() {
  int T;
  cin>>T;
  REP(cnt,T) {
    int n,s,t,f;
    cin>>n>>s>>t>>f;
    Matrix mat(n, Array(n));
    Array ary(n);
    REP(i,n) {
      REP(j,n) cin>>mat[i][j];
      cin>>ary[i];
    }
    auto p = LUPDecomposition(mat);
    Array temp = LUPBackSubstitution(p.first, p.second, ary);
    Graph g(n);
    REP(i,n) {
      int m;
      cin>>m;
      vector<int> to(m);
      REP(j,m)cin>>to[j];
      vector<int> fl(n);
      REP(j,m){
        int l;
        cin>>l;
        fl[to[j]] += l;
      }
      REP(j,n) {
        if (i != j && fl[j] != 0)
          add_edge(g, i, j, fl[j], abs(temp[i] - temp[j]));
      }
    }
    ld dmg = min_cost_flow(g, s, t, f);
    if (dmg >= 0.0)
      cout << setprecision(10) << fixed << dmg << endl;
    else
      cout << "impossible" << endl;
  }
  return 0;
}

Measured memory_bytes: 2704