#include <bits/stdc++.h>
using namespace std;
bool prime[100005];
vector<string> v(1005);
vector<long long> second;
long long a[10005];
bool vis[10005];
long long mat[1005][1005];
void dfs(long long src) {
  vis[src] = 1;
  second.push_back(src);
  for (long long i = 0; i < v[src].size(); i++) {
    if (v[src][i] == '1') {
      if (!vis[i]) {
        dfs(i);
      }
    }
  }
  return;
}
void sieve() {
  memset(prime, true, sizeof(prime));
  for (long long p = 2; p * p < 100005; p++) {
    if (prime[p] == true) {
      for (long long i = p * p; i < 100005; i += p) prime[i] = false;
    }
  }
}
long long powmod(long long x, long long y, long long mod) {
  long long res = 1;
  x = x % mod;
  while (y > 0) {
    if (y & 1) {
      res = (res * x) % mod;
    }
    y = y >> 1;
    x = (x * x) % mod;
  }
  return res;
}
signed main() {
  long long n;
  cin >> n;
  for (long long i = 0; i < n; i++) {
    cin >> a[i];
  }
  for (long long i = 0; i < n; i++) {
    cin >> v[i];
  }
  for (long long i = 0; i < n; i++) {
    if (!vis[i]) {
      second.clear();
      dfs(i);
      long long z = second.size();
      for (long long j = 0; j < z; j++) {
        for (long long k = 0; k < z; k++) {
          mat[second[j]][second[k]] = 1;
        }
      }
    }
  }
  for (long long i = 0; i < n; i++) {
    for (long long j = i + 1; j < n; j++) {
      if (a[i] > a[j]) {
        if (mat[i][j]) {
          swap(a[i], a[j]);
        }
      }
    }
  }
  for (long long i = 0; i < n; i++) {
    cout << a[i] << " ";
  }
  cout << endl;
  return 0;
}
