rt
//P1608 最短路统计
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,s,cnt,l,t,mn[2001][2001],head[2000005];
int dis[2000005],vis[2000005],ans[1000005];
struct edge{
int u,v,w,nxt;
}a[4000005];
struct node{
int w,p;
inline bool operator<(const node &x)const{
return w>x.w;
}
};
priority_queue<node>q;
void add(int u,int v,int w){
a[++cnt].u=u;
a[cnt].v=v;
a[cnt].w=w;
a[cnt].nxt=head[u];
head[u]=cnt;
}
signed main(){
cin>>n>>m;
for(int i=0;i<=n;i++) dis[i]=1e18;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
mn[i][j]=1e18;
}
}
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
if(w<mn[u][v]){
mn[u][v]=mn[v][u]=w;
add(u,v,w);
add(v,u,w);
}
}
dis[1]=0;
q.push((node){0,1});
ans[1]=1;
while(!q.empty()){
node x=q.top();
q.pop();
if(vis[x.p]) continue;
vis[x.p]=1;
for(int i=head[x.p];i;i=a[i].nxt){
int y=a[i].v;
if(dis[y]>dis[x.p]+a[i].w){
dis[y]=dis[x.p]+a[i].w;
ans[y]=ans[x.p];
q.push((node){dis[y],y});
}else if(dis[y]==dis[x.p]+a[i].w){
ans[y]+=ans[x.p];
}
}
}
if(dis[n]!=1e18) cout<<dis[n]<<' '<<ans[n]<<' ';
else cout<<"No answer ";
return 0;
}