#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <bits/stdc++.h>
#include<algorithm>
using namespace std;
typedef pair<int,int> p;
//ifstream fin("bfs.in");
//ofstream fout("bfs.out");
//ifstream fin("dfs.in");
//ofstream fout("dfs.out");
//ifstream fin("biconex.in");
//ofstream fout("biconex.out");
//ifstream fin("ctc.in");
//ofstream fout("ctc.out");
//ifstream fin("sortaret.in");
//ofstream fout("sortaret.out");
//ifstream fin("helsinki.in");
//ofstream fout("helsinki.out");
//ifstream fin("disjoint.in");
//ofstream fout("disjoint.out");
//ifstream fin("apm.in");
//ofstream fout("apm.out");
ifstream fin("dijkstra.in");
ofstream fout("dijkstra.out");
int viz[100001];
int first_value[100001];
int min_pos[100001];
stack <int> node_order;
int counter=0;
vector<int>biconex[100001];
vector<int>ctc[100001];
vector<int>sol_ctc[100001];
vector<int>sol_sortaret;
vector<int>hel;
vector<vector<int>>sol;
vector<int>graf[100001];
int tree[400001];
int height[100001];
int rang[100001];
int idx[100001];
vector<int>sol_kruskal;
int X[400001],Y[400001],C[400001];
vector<pair<int,int>>graf_d[50001];
int distanta_dijkstra[50001];
class grafMare
{
int N,M;
vector <int> graf[100001];
public:
grafMare(){};
int get_N();
void citireBFS();
void citireDFS();
void actualDFS(int);
void citire_biconex();
void add_a_biconex(int,int);
void DFS_biconex(int,int,int);
void citireCTC();
void DFS_CTC_1(int);
void DFS_CTC_2(int);
void citire_top();
void DFS_top(int);
bool helsinki();
void citire_helsinki();
void tarjan(int current_node, int current_pos, int tata_node)
{
min_pos[current_node]=current_pos;
first_value[current_node]=current_pos;
for(auto i : graf[current_node])
{
if(!min_pos[i])
{
tarjan(i, current_pos+1, current_node);
min_pos[current_node]=min(min_pos[current_node],min_pos[i]);
if(min_pos[i]>current_pos)
sol.push_back({current_node,i});
}
else if(i!=tata_node)
min_pos[current_node]=min(min_pos[current_node],first_value[i]);
}
}
vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections)
{
//first_value = vector<int>(n);
//min_pos = vector<int>(n);
for(auto x : connections)
{
graf[x[0]].push_back(x[1]);
graf[x[1]].push_back(x[0]);
}
tarjan(0,1,-1);
return sol;
}
void citire_pmd();
int radacina(int);
void combine(int,int);
void pmd_out();
void combine_apm_kruskal(int,int);
void citire_apm_kruskal();
void citire_dijkstra();
};
void grafMare::citire_dijkstra()
{
fin>>N>>M;
for(int i=0;i<M;i++)
{
int x,y,z;
fin>>x>>y>>z;
graf_d[x].push_back(make_pair(y,z));
}
for(int i=1;i<=N;i++)
distanta_dijkstra[i]=INT_MAX;
distanta_dijkstra[1]=0;
priority_queue<pair<int,int>>heap;
heap.push(make_pair(0,1));
for(int i=1;i<=N;i++)
viz[i]=0;
while(!heap.empty())
{
int current=heap.top().second;
heap.pop();
if(viz[current]==1)
continue;
else
viz[current]=1;
for(auto x:graf_d[current])
if(distanta_dijkstra[current]+x.second < distanta_dijkstra[x.first])
{
distanta_dijkstra[x.first]=distanta_dijkstra[current]+x.second;
heap.push(make_pair(-distanta_dijkstra[x.first],x.first));
}
}
for(int i=2;i<=N;i++)
if(distanta_dijkstra[i]!=INT_MAX)
fout<<distanta_dijkstra[i]<<" ";
else
fout<<0<<" ";
}
void grafMare::combine_apm_kruskal(int x,int y)
{
tree[x]=y;
}
bool sortare(int x,int y)
{
return C[x]<C[y];
}
void grafMare::citire_apm_kruskal()
{
int rez=0;
fin>>N>>M;
for(int i=1;i<=M;i++)
{
fin>>X[i]>>Y[i]>>C[i];
idx[i]=i;
}
for(int i=1;i<=N;i++)
{
tree[i]=i;
}
sort(idx+1,idx+M+1,sortare);
for(int i=1;i<=M;i++)
{
if(radacina(X[idx[i]]) != radacina(Y[idx[i]]) )
{
rez+=C[idx[i]];
combine_apm_kruskal(radacina(X[idx[i]]),radacina(Y[idx[i]]));
sol_kruskal.push_back(idx[i]);
}
}
fout<<rez<<"\n"<<N-1<<"\n";
for(int i=0;i<N-1;i++)
fout<<X[sol_kruskal[i]]<<" "<<Y[sol_kruskal[i]]<<"\n";
}
void grafMare::citire_pmd()
{
fin>>N>>M;
for(int i=1;i<=N;i++)
tree[i]=i;
for(int i=1;i<=N;i++)
rang[i]=1;
}
int grafMare::radacina(int x)
{
/*while(tree[x]!=x)
x=tree[x];
return x;*/
if(tree[x]==x)
return x;
tree[x]=radacina(tree[x]);
return tree[x];
}
void grafMare::combine(int x,int y)
{
if(rang[x]==rang[y])
{
tree[y]=x;
rang[x]++;
}
else if(rang[x]>rang[y])
tree[y]=x;
else
tree[x]=y;
}
void grafMare::pmd_out()
{
int a,x,y;
for(int i=0;i<M;i++)
{
fin>>a>>x>>y;
if(a==1)
combine(radacina(x),radacina(y));
else
{
if(radacina(x)==radacina(y))
fout<<"DA\n";
else
fout<<"NU\n";
}
}
}
bool grafMare::helsinki()
{
while(1)
{
sort(hel.begin(),hel.end(),greater<>());
if(hel[0]==0)//toate 0
return true;
int x=hel[0];
hel.erase(hel.begin());
if(x>hel.size())//destule elem
return false;
for(int i=0;i<x;i++)
{
hel[i]--;
if(hel[i]<0)//gasit elem negativ
return false;
}
}
}
void grafMare::citire_helsinki()
{
fin>>N;
for(int i=0;i<N;i++)
{
int x;
fin>>x;
hel.push_back(x);
}
fout<<helsinki();
}
void grafMare::DFS_top(int current_node)
{
viz[current_node]=1;
for(auto x : graf[current_node])
if(!viz[x])
DFS_top(x);
sol_sortaret.push_back(current_node);
}
void grafMare::citire_top()
{
fin>>N>>M;
for(int i=0;i<M;i++)
{
int a,b;
fin>>a>>b;
graf[a].push_back(b);
}
for(int i=1;i<=N;i++)
if(!viz[i])
DFS_top(i);
reverse(sol_sortaret.begin(),sol_sortaret.end());
for(auto x : sol_sortaret)
fout<<x<<" ";
}
void grafMare::citireCTC()
{
fin>>N>>M;
for(int i=0;i<M;i++)
{
int a,b;
fin>>a>>b;
graf[a].push_back(b);
ctc[b].push_back(a);
}
for(int i=1;i<=N;i++)
if(!viz[i])
DFS_CTC_1(i);
while(!node_order.empty())
{
if(viz[node_order.top()]==1)
{
counter++;
DFS_CTC_2(node_order.top());
}
node_order.pop();
}
fout<<counter<<"\n";
for(int i=1;i<=counter;i++)
{
for(auto x : sol_ctc[i])
fout<<x<<" ";
fout<<"\n";
}
}
void grafMare::DFS_CTC_1(int current_node)
{
viz[current_node]=1;
for(auto x : graf[current_node])
if(!viz[x])
DFS_CTC_1(x);
node_order.push(current_node);
}
void grafMare::DFS_CTC_2(int current_node)
{
viz[current_node]=2;
sol_ctc[counter].push_back(current_node);
for(auto x : ctc[current_node])
if(viz[x]==1)
DFS_CTC_2(x);
}
int grafMare::get_N()
{
return N;
}
void grafMare::citire_biconex()
{
fin>>N>>M;
for(int i=0;i<M;i++)
{
int a,b;
fin>>a>>b;
graf[a].push_back(b);
graf[b].push_back(a);
}
}
void grafMare::DFS_biconex(int current_node, int current_pos, int tata_node)
{
min_pos[current_node]=current_pos;
first_value[current_node]=current_pos;
node_order.push(current_node);
for(auto i : graf[current_node])
{
if(!min_pos[i]) //dfs
{
DFS_biconex(i, current_pos+1, current_node);
min_pos[current_node]=min(min_pos[current_node],min_pos[i]);
// actualizez levelul minim in caz ca baiatul urmator are traseu mai scurt de la un nod mai devreme, dupa ce intra in else if(desen 2, 7-8, 1-8)
if(min_pos[i] >= current_pos) // asta e punct de articulatie, daca n ar respecta cond asta, ins ca exista alt traseu care mentine conditia cu conex
{
counter++;
//current_node e first si i duce la ult elem din stack
while(node_order.top()!=i)
{
biconex[counter].push_back(node_order.top());
node_order.pop();
}
biconex[counter].push_back(node_order.top());
node_order.pop();
biconex[counter].push_back(current_node);
}
}
else if(i!=tata_node)
min_pos[current_node]=min(min_pos[current_node],first_value[i]);
}
}
void grafMare::citireBFS()
{
fin>>N>>M;
int start;
fin>>start;
int a,b;
for(int i=0;i<M;i++)
{
fin>>a>>b;
graf[a].push_back(b);
}
int sol[100001];
for(int i=0;i<N+1;i++)
sol[i]=-1;
queue <int> q;
q.push(start);
sol[start]=0;
while(!q.empty())
{
int first=q.front();
q.pop();
for(int vecin : graf[first])
{
if(sol[vecin]==-1)
{
sol[vecin]=sol[first]+1;
q.push(vecin);
}
}
}
for(int i=1;i<N+1;i++)
fout<<sol[i]<<" ";
}
void grafMare::actualDFS(int index)
{
for(int vecin : graf[index])
if(!viz[vecin])
{
viz[vecin]=1;
actualDFS(vecin);
}
}
void grafMare::citireDFS()
{
fin>>N>>M;
int start=1;
int a,b;
for(int i=0;i<M;i++)
{
fin>>a>>b;
graf[a].push_back(b);
graf[b].push_back(a);
}
for(int i=0;i<N+1;i++)
viz[i]=0;
for(int i=1;i<N+1;i++)
if(!viz[i])
{
counter++;
actualDFS(i);
}
fout<<counter;
}
int main()
{
grafMare gm;
//gm.citireBFS();
gm.citire_dijkstra();
}