/*
题目:
一个有n个节点的完全图,每条边、每个节点都有权值,在该图上求一个有m
个节点的生成树,使得该树的边权值和比点权和是所有m个节点的生成树中的
最小值,如果有多解输出字典序最小的
分析:
递归枚举m个节点,然后根据prim算法求的该比率,记录最小的边权和比点权
和最小的那棵树即可
*/
#include <cstdio>
#include <cstring>
const int X = 17;
#define INF 1e9
int map[X][X];
int wv[X],n,m;
bool use[X];
int ans[X];
int mnode[X];
double cnt;
int dis[X];
void prim() //prim算法求最小生成树
{
memset(use,false,sizeof(use));
memset(dis,0x7f,sizeof(dis));
int MIN,k;
int ret = 0;
dis[1] = 0;
for(int i=1;i<=m;i++)
{
MIN = INF;
for(int j=1;j<=m;j++)
if(!use[j]&&dis[j]<MIN)
MIN = dis[k = j];
ret += MIN;
use[k] = true;
for(int j=1;j<=m;j++)
if(!use[j]&&dis[j]>map[mnode[k]][mnode[j]])
dis[j] = map[mnode[k]][mnode[j]];
}
int node_w = 0;
for(int i=1;i<=m;i++)
node_w += wv[mnode[i]];
double temp = ret*1.0/node_w;
if(cnt>temp)
{
cnt = temp;
for(int i=1;i<=m;i++)
ans[i] = mnode[i];
}
}
void solve(int have,int cur) //递归枚举m个节点
{
if(have==m+1)
{
prim();
return;
}
for(int i=cur;i<=n;i++)
{
mnode[have] = i;
solve(have+1,i+1);
}
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
while(scanf("%d%d",&n,&m),n||m)
{
cnt = INF;
for(int i=1;i<=n;i++)
scanf("%d",&wv[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&map[i][j]);
solve(1,1);
printf("%d",ans[1]);
for(int i=2;i<=m;i++)
printf(" %d",ans[i]);
printf("\n");
}
return 0;
}