//无向网的建立(采用邻接矩阵) 
#include<iostream>
using namespace std;

const int Max=50,MaxVal=1001; //设顶点数最多为50,权值最大值为1000
bool visited[Max];

struct MGraph{//图的定义 
    int mat[Max][Max];//弧的信息 
    int vexnum;//顶点数 
    void InitG(int n);//初始化 
    void CreateG(int n,int m);//建立图 
    void Traverse();//遍历 
}; 
//初始化一个顶点总数为m的网
void MGraph::InitG(int n)
{
    vexnum=n;
    //fill(&mat[0][0],&mat[vexnum-1][vexnum-1]+1,0);//初始图的情况 
    for(int i=0;i<vexnum;i++)//右边写权值,没边写无穷,自己到自己是0,一开始全部是无穷 
    {
        for(int j=0;j<vexnum;j++)
        {
            mat[i][j]=MaxVal;
        }
        mat[i][i]=0;
    }
 } 
 
 //建立n个顶点,m条边的无向网
 
 void MGraph::CreateG(int n,int m)
 {
     InitG(n);
     for(int j=0;j<m;j++)
     {
         int a,b,c;
         cin>>a>>b>>c;//编号从一开始用 ,a到b有边,权值是c; 
         a--;//下标从0开始用 
         b--;
         mat[a][b]=c;
         mat[b][a]=c;//有向网去除此条语句 
         //建图 mat[a][b]=1;有向图,c权值不用输入 
     }
  } 
  
 void MGraph::Traverse(){
     for(int i=0;i<vexnum;i++)
     {
         for(int j=0;j<vexnum;j++)
         {
             if(j>0) cout<<" ";
             cout<<mat[i][j];
         }
         cout<<endl;
     }
 } 

int main(){
    MGraph g;
    int n,m;
    cin>>n>>m;
    g.CreateG(n,m);
    g.Traverse();
    return 0;
}