//UVA1609FoulPlay
#include<cstdio>
#include<cstdlib>
#include<vector>
using namespace std;
const int MAXN = (1 << 10) + 5;
char table[MAXN][MAXN];
int main() {
int n;
while(scanf("%d", &n) == 1 && n) {
getchar();
for(int i = 1; i <= n; i++) fgets(table[i] + 1, sizeof(table[i]), stdin);
/*printf("***\n");
*/vector<int> win, lose;
for(int i = 2; i <= n; i++) {
if(table[1][i] == '1') win.push_back(i);
else lose.push_back(i);
}//收集所1队的对战信息
/*for(int i = 0; i < win.size(); i++) printf("%2d", win[i]);
printf("\n");
for(int i = 0; i < lose.size(); i++) printf("%2d", lose[i]);
printf("\n");
*/int r = n;
while(r > 1) {
/* printf("r = %d\n", r);
*/ vector<int> win2, lose2, left;
for(int i = 0; i < lose.size(); i++) {//i从1开始,跳过自己
bool match = false;
for(int j = 0; j < win.size(); j++) {
if(win[j] > 0 && table[win[j]][lose[i]] == '1') {//找到一组配对,用自己打得过的队,去打自己打不过的队
match = true;
int& twin = win[j];
printf("%d %d\n", win[j], lose[i]);
win2.push_back(win[j]);//进入下一轮
twin = 0; //不可重复使用同一支球队
/* printf("win[j] = %d, j = %d\n", win[j], j);
*/ break;
}
}
if(!match) left.push_back(lose[i]);
}
/* printf("left:\n");
for(int i = 0; i < left.size(); i++) printf("%d ---\n", left[i]);
*/ bool tag = true;
/* printf("123321321313213123213\n");
*/ for(int i = 0; i < win.size(); i++) {
if(win[i] > 0) {
/* printf("win[%d] = %d\n", i, win[i]);
*/ if(tag) {
printf("%d %d\n", 1, win[i]); tag = false;
}
else left.push_back(win[i]);
}
}//给1队配对
/* printf("leftsize = %d\\\\\n", left.size());
*/ for(int i = 0; i < left.size(); i += 2) {
printf("%d %d\n", left[i], left[i + 1]);
int keep = left[i];
if(table[keep][left[i + 1]] == '0') keep = left[i + 1];
if(table[1][keep] == '1') win2.push_back(keep);
else lose2.push_back(keep);
}
lose = lose2;
win = win2;
r >>= 1;
}
}
return 0;
}
/*
4
0110
0011
0000
1010
8
00111010
10101111
00010010
01000101
00110010
10101011
00010000
10101010
*/