// Solution to Sofa, So Good
//
// Basically just copied from TopCoder:
//   http://community.topcoder.com
//                      /tc?module=Static&d1=tutorials&d2=hungarianAlgorithm
// but changing some variable names and negating all input values to convert 
// maximize to minimize.

import java.util.*;

public class SofaB {
  public static Scanner in;
  public static int n, caseNum;
  public static int[][] fr, up, idle; // framing, upholstering, idle times
  public static int[][] c; // parameter
  public static int matched, maxwt; // # edges and weight of matching
  public static int[] wlabel, slabel; // worker, sofa labels
  public static int[] wmatch, smatch; // nbrs in matching
  public static boolean[] s,t; // sets used in augmentation
  public static int[] prev, slack, slackx;

  public static void main(String[] args) {
    in = new Scanner(System.in);
    caseNum = 0;
    while(true) {
      n = in.nextInt();
      if (n == 0) break;
      caseNum++;
      fr = new int[n][n];
      up = new int[n][n];
      idle = new int[n][n];
      for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
          fr[i][j] = -in.nextInt(); // negative since max matching
      for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
          up[i][j] = -in.nextInt();
      c = fr;
      solve();
      // Save results so we can re-use wmatch array:
      int phase1[] = new int[n];
      for (int i = 0; i < n; i++) {
        phase1[i] = wmatch[i];
      }
      adjust();
      c = up;
      solve();
      int totidle = 0;
      System.out.println("Case " + caseNum + ":");
      for (int i = 0; i< n; i++) {
        System.out.print("Worker " + (i+1) + ": ");
        System.out.print((1+phase1[i])+" "+(1+wmatch[i])+" ");
        System.out.println(-fr[i][phase1[i]]
                          -up[i][wmatch[i]]);
        totidle+=(idle[i][wmatch[i]]);
      }
      System.out.println("Total idle time: " + totidle);
      
    }
  }

  // Algorithm/code borrowed from:
  // http://community.topcoder.com/
  //           tc?module=Static&d1=tutorials&d2=hungarianAlgorithm
  // For a while I added my own comments to explain to myself what
  // was going on...

  public static void solve() {
    // Initial empty matching:
    maxwt = 0; // max so far (which we negate to get min)
    matched = 0; // number of edges in current matching
    wmatch = new int[n];
    Arrays.fill(wmatch,-1);
    smatch = new int[n];
    Arrays.fill(smatch,-1);

    // Initial feasible labeling:
    wlabel = new int[n];
    slabel = new int[n];
    Arrays.fill(wlabel,0);
    Arrays.fill(slabel,0); // sofa labels all 0
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        wlabel[i] = Math.max(wlabel[i],c[i][j]); // worker labels = max edge
    // The hard part:
    augment();
  }

  public static void adjust() {
    // Add time to the appropriate entries in "up" based upon
    // framing results. If worker i finished framing sofa
    // wmatch[i] at time t1, and worker smatch[j] finishes
    // framing sofa j at time t2, worker i must wait an additional
    // t2-t1 minutes to frame sofa j if t2 > t1, 0 otherwise.

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        idle[i][j] = Math.max(0,fr[i][wmatch[i]]-fr[smatch[j]][j]);
        up[i][j] -= idle[i][j];
      }
    }
  }

  public static void augment() {
    if (matched==n) return;
    int x, y, root=-1;
    int q[] = new int[n];
    int wr=0,rd=0;
    s = new boolean[n];
    t = new boolean[n];
    Arrays.fill(s,false);
    Arrays.fill(t,false);
    prev = new int[n];
    Arrays.fill(prev,-1);

    // Look for an exposed vertex in the equality graph:
    for (x = 0; x < n; x++) {
      if (wmatch[x] == -1) {
        q[wr++] = root = x; // root of alt. tree; queued for BFS
        prev[x] = -2; // no parent in tree since root
        s[x] = true;  // place x in s
        break; // found root of aug tree--done
      }
    }

    // Build alt. path tree. At some point we are going to
    // need to find smallest difference between edge cost
    // and label cost; slack helps us find that and slackx
    // helps us remember where the label changes have to take place.
    slack = new int[n];
    slackx = new int[n];
    for (y = 0; y < n; y++) {
      slack[y] = wlabel[root]+slabel[y]-c[root][y];
      slackx[y] = root;
    }

    while (true) //main cycle
    {
      while (rd < wr) //building tree with bfs cycle
      {
        x = q[rd++]; //current vertex from X part
        for (y = 0; y < n; y++) //iterate through all edges in equality graph
          if (c[x][y] == wlabel[x] + slabel[y] &&  !t[y])
          {
            if (smatch[y] == -1) break; //an exposed vertex in Y found, so
                                    //augmenting path exists!
            t[y] = true; //else just add y to T,
            q[wr++] = smatch[y]; //add vertex smatch[y], which is matched
                               //with y, to the queue
            add(smatch[y], x); //add edges (x,y) and (y,smatch[y]) to the tree
          }
        if (y < n) break; //augmenting path found!
      }
      if (y < n) break; //augmenting path found!
      update(); //augmenting path not found, so improve labeling
      wr = rd = 0;                
      for (y = 0; y < n; y++)        
        //in this cycle we add edges that were added to the equality
        //graph as a result of improving the labeling, we add 
        // edge (slackx[y], y) to the tree if and only if !T[y] 
        // &&  slack[y] == 0, also with this edge we add another one
        // (y, smatch[y]) or augment the matching, if y was exposed
        if (!t[y] &&  slack[y] == 0)
        {
          if (smatch[y] == -1) //exposed vertex in Y found - augmenting path exists!
          {
            x = slackx[y];
            break;
          }
          else
          {
            t[y] = true; //else just add y to T,
            if (!s[smatch[y]])    
            {
              q[wr++] = smatch[y]; //add vertex smatch[y], which is matched with
                                   //y, to the queue
              add(smatch[y], slackx[y]); //and add edges (x,y) and (y,
                                         //smatch[y]) to the tree
             }
           }
         }
       if (y < n) break; //augmenting path found!
    }

    if (y < n) //we found augmenting path!
    {
       matched++; //increment matching
        //in this cycle we inverse edges along augmenting path
        for (int cx = x, cy = y, ty; cx != -2; cx = prev[cx], cy = ty)
        {
            ty = wmatch[cx];
            smatch[cy] = cx;
            wmatch[cx] = cy;
        }
        augment(); //recall function, go to step 1 of the algorithm
    }
  }

  public static void update() {
    int x, y, delta = Integer.MAX_VALUE;

    // delta = smallest slack value in the complement of
    // neighborhood of workers in equality graph 
    for (y = 0; y < n; y++) {
      if (!t[y]) delta = Math.min(delta,slack[y]);
    }

    // Apply delta to edges not in equality graph:
    for (x = 0; x < n; x++)
      if (s[x]) wlabel[x] -= delta;
    for (y = 0; y < n; y++)
      if (t[y]) slabel[y] += delta;
    for (y = 0; y < n; y++)
      if (!t[y]) slack[y] -= delta;
  }

  public static void add(int x, int prevx) {
    s[x] = true;
    prev[x] = prevx;
    for (int y = 0; y < n; y++)
      if (wlabel[x]+slabel[y] - c[x][y] < slack[y]) {
        slack[y] = wlabel[x]+slabel[y]-c[x][y];
        slackx[y] = x;
      }
  }

  // For debugging:
  public static void show() {
    System.out.println("Frame:");
    System.out.print("  ");
    for (int i = 0; i < n; i++)
       System.out.printf("%5d",i);
    System.out.println();
    for (int i = 0; i < n; i++) {
       System.out.printf("%2d ",i);
       for (int j = 0; j < n; j++)
         System.out.printf("%5d",fr[i][j]);
       System.out.println();
    }
    System.out.println("Upholster:");
    System.out.print("  ");
    for (int i = 0; i < n; i++)
       System.out.printf("%5d",i);
    System.out.println();
    for (int i = 0; i < n; i++) {
       System.out.printf("%2d ",i);
       for (int j = 0; j < n; j++)
         System.out.printf("%5d",up[i][j]);
       System.out.println();
    }
  }
}
