// Accepted 1385 46MS 424K 3948 B C++
//点和边均有权值 路径按字典顺序小的输出
#include<iostream>
#include<cstdio>
#include<queue>
#define MAX 0x3fffffff
#define asize 10002
using namespace std;
struct node{
node(int vv=0,int dd=0):vexn(vv),dist(dd){}
int vexn;
int dist;
friend bool operator<(node a,node b)
{
return a.dist> b.dist;
}
};
bool hash[asize];
int dis[asize],cost[asize][asize];
int count1,n,m;
int tas[asize],ts[asize],path[asize];
bool lexically(int u,int j,int v0)
{
int path_1[asize];
int path_2[asize];
int i;
int len1=0,len2 = 0;
path_1[len1++]=j;
for(i = u;;i = path[i])
{
path_1[len1++] = i;
if(i == v0)
{
break;
}
}
len1--;
for(i = j;;i = path[i])
{
path_2[len2++] = i;
if(i == v0)
{
break;
}
}
len2--;
int len=len1<len2?len1:len2;
for (i=0;i<=len;++i)
{
if (path_1[len1-i]<path_2[len2-i])
{
return true;
}
if (path_1[len1-i]>path_2[len2-i])
{
return false;
}
}
if(len1<len2)
{
return true;
}
return false;
}
int djkstra(int v0,int ve)
{
priority_queue<node> q;
int i;
for(i = 1; i <= n; i++)
{
dis[i] = MAX;
ts[i] = tas[i];
path[i] = -1;
}
memset(hash,true, sizeof(hash));
// memset(pathlen,1,sizeof(pathlen));
dis[v0] = 0;
ts[v0] = 0;
//ts[ve] = 0;
path[v0] = v0;
q.push(node(v0,dis[v0]));
node N;
while(!q.empty())
{
N = q.top();
q.pop();
if(!hash[N.vexn])continue;
hash[N.vexn] = false;
for(i = 1; i <= n; i++)
{
if(hash[i] && N.dist + cost[N.vexn][i] + ts[i]< dis[i] && cost[N.vexn][i] != -1 )
{
dis[i] = N.dist + cost[N.vexn][i] + ts[i];
path[i] = N.vexn;
//pathlen[i] = pathlen[N.vexn] + 1;
q.push(node(i,dis[i]));
}
else if(hash[i] && N.dist + cost[N.vexn][i] + ts[i] == dis[i] && cost[N.vexn][i] != -1 )
{
if(lexically(N.vexn,i,v0))
{
dis[i] = N.dist + cost[N.vexn][i] + ts[i];
path[i] = N.vexn;
// pathlen[i] = pathlen[N.vexn] + 1;
//q.push(node(i,dis[i]));
}
}
}
}
//if(dis[n] == MAX)
//return -1;
return dis[ve] - ts[ve];
}
void showpath(int v0,int ve)
{
int i,k;
int p[asize];
k = 0;
for(i = ve;;i = path[i])
{
if(path[i] == -1)
{
printf("没有路径/n");
return;
}
p[k++] = i;
if(i == v0)
{
break;
}
}
for(i = k - 1;i >= 0;i--)
{
printf("%d",p[i]);
if(i)
{
printf("-->");
}
}
printf("/n");
}
void INIT(int n)
{
int i,j;
//count1 = 0;
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
scanf("%d",&cost[i][j]);
}
}
for(i = 1; i <= n; i++)
{
scanf("%d",&tas[i]);
}
}
int main()
{
int i,w,b,j,a;
int s,t,res;
while(scanf("%d",&n) != EOF && n)
{
INIT(n);
while(1)
{
scanf("%d%d",&a,&b);
if(a == -1 && b == -1)
break;
res = djkstra(a,b);
printf("From %d to %d :/n",a,b);
printf("Path: ");
showpath(a,b);
printf("Total cost : %d/n/n",res);
}
}
}