You are given a weighted undirected connected graph consisting of n vertices and m edges. It is guaranteed that there are no self-loops or multiple edges in the given graph.

Let's define the weight of the path consisting of k edges with indices e_1, e_2, ..., e_k as ∑_{i=1}^{k}{w_{e_i}} - max_{i=1}^{k}{w_{e_i}} + min_{i=1}^{k}{w_{e_i}}, where w_i — weight of the i-th edge in the graph.

Your task is to find the minimum weight of the path from the 1-st vertex to the i-th vertex for each i (2 ≤ i ≤ n).

Input

The first line contains two integers n and m (2 ≤ n ≤ 2 ⋅ 10^5; 1 ≤ m ≤ 2 ⋅ 10^5) — the number of vertices and the number of edges in the graph.

Following m lines contains three integers v_i, u_i, w_i (1 ≤ v_i, u_i ≤ n; 1 ≤ w_i ≤ 10^9; v_i ≠ u_i) — endpoints of the i-th edge and its weight respectively.

Output

Print n-1 integers — the minimum weight of the path from 1-st vertex to the i-th vertex for each i (2 ≤ i ≤ n).

Examples

Input


5 4
5 3 4
2 1 1
3 2 2
2 4 2


Output


1 2 2 4 


Input


6 8
3 1 1
3 6 2
5 4 2
4 2 2
6 1 1
5 2 1
3 2 3
1 5 4


Output


2 1 4 3 1 


Input


7 10
7 5 5
2 3 3
4 7 1
5 3 6
2 7 6
6 2 6
3 7 6
4 2 1
3 1 4
1 7 4


Output


3 4 2 7 7 3 
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.stream.Stream;

import java.util.Iterator;
import java.util.List;
import java.util.Map;


public class Main {
	
static class DijkstraCustomHeap {
    // calculate shortest paths in O(E*log(V)) time and O(V) memory
    public static void shortestPaths(List<Edge>[] edges, int s, long[] prio, int[] pred) {
        Arrays.fill(pred, -1);
        Arrays.fill(prio, Long.MAX_VALUE);
        prio[s] = 0;
        BinaryHeap h = new BinaryHeap(edges.length);
        h.add(s, 0);
        while (h.size != 0) {
            int u = h.remove();
            for (Edge e : edges[u]) {
                int v = e.t;
                long nprio = prio[u] + e.cost;
                if (prio[v] > nprio) {
                    if (prio[v] == Long.MAX_VALUE)
                        h.add(v, nprio);
                    else
                        h.increasePriority(v, nprio);
                    prio[v] = nprio;
                    pred[v] = u;
                }
            }
        }
    }

//    // Usage example
//    public static void main(String[] args) {
//        int[][] cost = {{0, 3, 2}, {0, 0, -2}, {0, 0, 0}};
//        int n = cost.length;
//        List<Edge>[] edges = Stream.generate(ArrayList::new).limit(n).toArray(List[] ::new);
//        for (int i = 0; i < n; i++) {
//            for (int j = 0; j < n; j++) {
//                if (cost[i][j] != 0) {
//                    edges[i].add(new Edge(j, cost[i][j]));
//                }
//            }
//        }
//        long[] dist = new long[n];
//        int[] pred = new int[n];
//        shortestPaths(edges, 0, dist, pred);
//        System.out.println(0 == dist[0]);
//        System.out.println(3 == dist[1]);
//        System.out.println(1 == dist[2]);
//        System.out.println(-1 == pred[0]);
//        System.out.println(0 == pred[1]);
//        System.out.println(1 == pred[2]);
//    }
}


static class Edge {
    int t;
    int cost;

    public Edge(int t, int cost) {
        this.t = t;
        this.cost = cost;
    }
}

static class BinaryHeap {
    long[] heap;
    int[] pos2Id;
    int[] id2Pos;
    int size;

    public BinaryHeap(int n) {
        heap = new long[n];
        pos2Id = new int[n];
        id2Pos = new int[n];
    }

    public int remove() {
        int removedId = pos2Id[0];
        heap[0] = heap[--size];
        pos2Id[0] = pos2Id[size];
        id2Pos[pos2Id[0]] = 0;
        down(0);
        return removedId;
    }

    public void add(int id, long value) {
        heap[size] = value;
        pos2Id[size] = id;
        id2Pos[id] = size;
        up(size++);
    }

    public void increasePriority(int id, long value) {
        heap[id2Pos[id]] = value;
        up(id2Pos[id]);
    }

    void up(int pos) {
        while (pos > 0) {
            int parent = (pos - 1) / 2;
            if (heap[pos] >= heap[parent])
                break;
            swap(pos, parent);
            pos = parent;
        }
    }

    void down(int pos) {
        while (true) {
            int child = 2 * pos + 1;
            if (child >= size)
                break;
            if (child + 1 < size && heap[child + 1] < heap[child])
                ++child;
            if (heap[pos] <= heap[child])
                break;
            swap(pos, child);
            pos = child;
        }
    }

    void swap(int i, int j) {
        long tt = heap[i];
        heap[i] = heap[j];
        heap[j] = tt;
        int t = pos2Id[i];
        pos2Id[i] = pos2Id[j];
        pos2Id[j] = t;
        id2Pos[pos2Id[i]] = i;
        id2Pos[pos2Id[j]] = j;
    }
}


	


public static void main(String[] args){
 
   new Thread(null, null, "Anshum Gupta", 99999999) {
        public void run() {
            try {
                solve();
            } catch(Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }.start();
}
 

static final long INF_LONG = (long)(1e18 + 5), MOD = (long)1e9 + 7;//998244353; 
static final int MXN = (int)(1001), MXV = (int)(1e6 + 5), log = 18, INF = (int)1e9 + 500;
static ArrayList<ArrayList<Integer>> adj;
static boolean[][] vis;
static char[] S;
static int N, M, K, Q, H, W;


public static void solve() throws Exception {
	   // solve the problem here
		s = new MyScanner();
   		out = new MyWriter(new BufferedOutputStream(System.out));
   		
        int T = 1;//s.nextInt();
        
        for(int i = 1; i <= T; i++) testcase();
          
        out.flush();
        out.close();
}


static void testcase() {
	
	N = s.nextInt();
	M = s.nextInt();
	DijkstraCustomHeap dij = new DijkstraCustomHeap();
	List<Edge>[] edges = new ArrayList[4 * N];
	for(int i = 0; i < 4 * N; i++) edges[i] = new ArrayList<Edge>();
	
	for(int i = 0; i < M; i++) {
		int u = s.nextInt(), v = s.nextInt(), w = s.nextInt();
		u--; v--;
		
		for(int it = 0; it < 2; it++) {
			
			for(int j = 0; j < 4; j++) {
				edges[4 * u + j].add(new Edge(4 * v + j, w));
			}
			
			edges[4 * u].add(new Edge(4 * v + 3, w));
			
			edges[4 * u].add(new Edge(4 * v + 2, 0));
			edges[4 * u + 1].add(new Edge(4 * v + 3, 0));
			
			edges[4 * u].add(new Edge(4 * v + 1, w * 2));
			edges[4 * u + 2].add(new Edge(4 * v + 3, w * 2));
			
			int temp = u;
			u = v;
			v = temp;
			
		}
		
		
	}
	
	long[] distance = new long[4 * N];
	
	dij.shortestPaths(edges, 0, distance, new int[4 * N]);
	
	for(int i = 1; i < N; i++) {
		out.print(distance[4 * i + 3] +  " ");
	}
	
	out.println();	
	
	
}




public static MyWriter out;
public static MyScanner s;
static void shuffleArray(int[] a) {
	Random random = new Random();
	for (int i = a.length-1; i > 0; i--) {
		int index = random.nextInt(i + 1);
		int tmp = a[index];
		a[index] = a[i];
		a[i] = tmp;
	}
}
static void shuffleSort(int[] a) {
	shuffleArray(a);
	Arrays.parallelSort(a);
}

static void shuffleArray(long[] a) {
	Random random = new Random();
	for (int i = a.length-1; i > 0; i--) {
		int index = random.nextInt(i + 1);
		long tmp = a[index];
		a[index] = a[i];
		a[i] = tmp;
	}
}
static void shuffleSort(long[] a) {
	shuffleArray(a);
	Arrays.parallelSort(a);
}

static void reverse(int[] a) {
	int[] copy = Arrays.copyOf(a, a.length);
	for(int i = 0; i < a.length; i++) {
		a[a.length - 1 - i] = copy[i];
	}
}

static class MyScanner {
 
    BufferedReader br;
    StringTokenizer st;
 
    public MyScanner() {
        br = new BufferedReader(new InputStreamReader(System.in));
    }
    public MyScanner(String fileName) {
    	try {
			br = new BufferedReader(new FileReader(fileName));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
    }
    String next() {
        while (st == null || !st.hasMoreElements()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return st.nextToken();
    }
 
    int nextInt() { return Integer.parseInt(next()); }
    long nextLong() { return Long.parseLong(next()); }
    double nextDouble() { return Double.parseDouble(next()); }
    int[] nextIntArray(int n){
    	int[] a = new int[n];
    	for(int i = 0; i < n; i++) {
    		a[i] = this.nextInt();
    	}
    	return a;
    }
    long[] nextlongArray(int n) {
    	long[] a = new long[n];
    	for(int i = 0; i < n; i++) {
    		a[i] = this.nextLong();
    	}
    	return a;
    }
    Integer[] nextIntegerArray(int n){
    	Integer[]a = new Integer[n];
    	for(int i=0; i<n; i++) {
    		a[i] = this.nextInt();
    	}
    	return a;
    }
    Long[] nextLongArray(int n) {
    	Long[]a = new Long[n];
    	for(int i=0; i<n; i++) {
    		a[i] = this.nextLong();
    	}
    	return a;
    }
    char[][] next2DCharArray(int n, int m){
    	char[][]arr = new char[n][m];
    	for(int i=0; i<n; i++) {
    		arr[i] = this.next().toCharArray();
    	}
    	return arr;
    }
    ArrayList<ArrayList<Integer>> readUndirectedUnweightedGraph(int n, int m) {
    	ArrayList<ArrayList<Integer>>adj = new ArrayList<ArrayList<Integer>>();
    	for(int i = 0; i < n; i++)adj.add(new ArrayList<Integer>());
    	for(int i = 0; i < m; i++) {
    		int u = s.nextInt();
    		int v = s.nextInt();
    		u--; v--;
    		adj.get(u).add(v);
    		adj.get(v).add(u);
    	}
    	return adj;
    }
    ArrayList<ArrayList<Integer>> readDirectedUnweightedGraph(int n, int m) {
    	ArrayList<ArrayList<Integer>>adj = new ArrayList<ArrayList<Integer>>();
    	for(int i = 0; i < n; i++)adj.add(new ArrayList<Integer>());
    	for(int i = 0; i < m; i++) {
    		int u = s.nextInt();
    		int v = s.nextInt();
    		u--; v--;
    		adj.get(u).add(v);
    	}
    	return adj;
    }
    String nextLine(){
        String str = "";
        try {
            str = br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str;
    }
}
 
static class MyWriter extends PrintWriter {
    MyWriter(OutputStream out) {
        super(out);
    }
    void println(int[] x) {
        println(x, " ");
    }
    void println(int[] x, String delimiter) {
        if (x.length > 0) {
            print(x[0]);
            for (int i = 1; i < x.length; i++) {
                print(delimiter);
                print(x[i]);
            }
        }
        println();
    }
    void println(long[] x) {
        println(x, " ");
    }
    void println(long[] x, String delimiter) {
        if (x.length > 0) {
            print(x[0]);
            for (int i = 1; i < x.length; i++) {
                print(delimiter);
                print(x[i]);
            }
        }
        println();
    }
    void println(Iterable<?> iterable) {
        println(iterable, " ");
    }
    void println(Iterable<?> iterable, String delimiter) {
        Iterator<?> i = iterable.iterator();
        if (i.hasNext()) {
            print(i.next());
            while (i.hasNext()) {
                print(delimiter);
                print(i.next());
            }
        }
        println();
    }
    void printLines(int[] x) {
        println(x, System.lineSeparator());
    }
    void printLines(long[] x) {
        println(x, System.lineSeparator());
    }
    void printLines(Iterable<?> iterable) {
        println(iterable, System.lineSeparator());
    }
}
 
}