#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 100
typedef struct dj {
int vn;
char vertex[MAX];
int edge[MAX][MAX];
int cost[MAX][MAX];
char route[MAX][MAX];
} DJ;
typedef struct node {
char vertex;
struct node * next;
} ND;
int getindex(char v0,char vt[],int n);
void add(ND * head,ND * tail,char vertex,ND * res[]);
ND *del(ND *head);
void BFS(DJ graph,char v0,char vt[],int visited[]);
void clear(char route[MAX][MAX],int n);
void copy(char s[MAX],char d[MAX]);
void append(char target[MAX],char ch);
char min(int cost[MAX][MAX],char vt[],int visited[],int vn);
void update(int cost[MAX][MAX],char route[MAX][MAX],char vt[],char start,char end,int n);
void proute(char route[MAX][MAX],int bridge);
int main(int argc,char *argv[]) {
DJ graph;
scanf("%d",&graph.vn);
char temp = '\0';
int visited[MAX] = {0};
temp = getchar();
int i = 0,j = 0;
for(i = 0; i < graph.vn; i++) {
scanf("%c",&graph.vertex[i]);
temp = getchar();
}
for(i = 0; i < graph.vn; i++) {
for(j = 0; j < graph.vn; j++) {
scanf("%d",&graph.edge[i][j]);
}
}
for(i = 0; i < graph.vn; i++) {
for(j = 0; j < graph.vn; j++) {
scanf("%d",&graph.cost[i][j]);
}
}
BFS(graph,'a',graph.vertex,visited);
return 0;
}
int getindex(char v0,char vt[],int n) {
int i = 0;
for(i = 0; i < n; i++) {
if(v0 == vt[i]) {
return i;
}
}
return -1;
}
void BFS(DJ graph,char v0,char vt[],int visited[]) {
char temp[] = {};
int i = 0,index = 0,isnd = 0;
char bridge = '\0';
index = getindex(v0,vt,graph.vn);
for(i = 0; i < graph.vn; i++) {
if(graph.edge[index][i] == 1&&visited[i] == 0) {
update(graph.cost,graph.route,vt,vt[index],vt[i],graph.vn);
}
}
visited[index] = 1;
if(index == 0) printf("%c->%c\n",vt[index],vt[index]);
bridge = min(graph.cost,vt,visited,graph.vn);
proute(graph.route,getindex(bridge,vt,graph.vn));
isnd = isend(visited,graph.vn);
if(isnd == 0) BFS(graph,bridge,vt,visited);
}
void update(int cost[MAX][MAX],char route[MAX][MAX],char vt[],char start,char end,int n) {
int inds = 0,inde = 0,index = 0;
inds = getindex(start,vt,n);
inde = getindex(end,vt,n);
if(cost[0][inds] + cost[inds][inde] <= cost[0][inde]) {
cost[0][inde] = cost[0][inds] + cost[inds][inde];
clear(route,inde);
copy(route[inds],route[inde]);
append(route[inde],vt[inde]);
}
}
void clear(char route[MAX][MAX],int n) {
int i = 0;
for(i = 0; i < MAX; i++) {
route[n][i] = '\0';
}
}
void copy(char s[MAX],char d[MAX]) {
int i = 0;
for(i = 0; i < MAX; i++) {
d[i] = s[i];
}
}
void append(char target[MAX],char ch) {
int i = 0;
for(i = 0; i < MAX; i++) {
if(target[i] == '\0') {
target[i] = ch;
target[i+1] = '\0';
break;
}
}
}
char min(int cost[MAX][MAX],char vt[],int visited[],int vn) {
int i = 0,min = 100;
char result = '\0';
for(i = 1; i < vn; i++) {
if(min > cost[0][i]&&visited[i] == 0) {
min = cost[0][i];
result = vt[i];
}
}
return result;
}
void proute(char route[MAX][MAX],int bridge) {
int i = 0;
if(bridge == -1);
else {
for(i = 0; i < strlen(route[bridge]) - 1; i++) {
printf("%c->",route[bridge][i]);
}
printf("%c\n",route[bridge][i]);
}
}
int isend(int visited[],int vn) {
int i = 0;
for(i = 0; i < vn; i++) {
if(visited[i] == 0) return 0;
}
return 1;
}