//基于迪杰斯特拉算法和弗洛伊德算法的最短路
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
const int inf = 0x3f3f3f3f;
int G[1000][1000];
bool vis[1000];
int n;
int main()
{
//建立邻接矩阵,没有边距离为-1;
std::cin>>n;
for(int i = 0; i < n; i++ )
for(int j = 0; j < n; j++)
{
std::cin>>G[i][j];
}
//迪杰斯特拉算法,算出其他点到点k的最短距离
int k;
std::cin>>k;
int dis[1000];//保存点k到其他点的距离
//初始化
memset(vis,false,sizeof(vis));
memset(dis,-1,sizeof(dis));
for(int i = 0; i < n; i++)
{
if(i != k)
dis[i] = G[k][i];
if(dis[i] == -1)
dis[i] = inf;
}
vis[k] = true;
for(int i = 0; i < n; i++)
{
int mindis = inf;
int temp = k;
//找出每一次距离最小的点temp
for(int j = 0; j < n; j++)
{
if(!vis[j] && dis[j] < mindis)
{
temp = j;
mindis = dis[temp];
}
}
vis[temp] = true;
//更新到其他点的最小距离
for(int j = 0; j < n; j++)
{
if(!vis[j] && G[temp][j] < inf)
{
if(dis[temp] + G[temp][j] < dis[j])
dis[j] = dis[temp]+G[temp][j];
}
}
}
//弗洛伊德
int dis2[1000][1000];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
dis2[i][j] = G[i][j];
}
}
//对每三个点之间都进行一次松弛操作,这样所以的点之间都会是最短的
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
for(int k = 0; k < n; k++)
{
if(dis2[i][k] + dis2[k][j] < dis2[i][j])
dis2[i][j] = dis2[i][k] + dis2[k][j];
}
}
}
return 0;
}