#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
const int maxn = 1e6 + 10;
const long long mod = 1e9 + 7;
int label[maxn], dis[maxn];
namespace Trie {
int tot, next[maxn][10];
int fa[maxn], jump[20][maxn], wfa[maxn], dth[maxn];
long long val[maxn];
void init(int x) {
  jump[0][x] = fa[x];
  for (int i = 1; i <= 19; i++) jump[i][x] = jump[i - 1][jump[i - 1][x]];
}
int insert(int x, string s) {
  int cur = x, l = s.length();
  for (int i = 0; i < l; i++) {
    if (!next[cur][s[i] - '0']) {
      next[cur][s[i] - '0'] = ++tot, fa[tot] = cur, wfa[tot] = s[i] - '0',
                       dth[tot] = dth[cur] + 1, init(tot);
      val[tot] = (val[cur] * 10 + s[i] - '0') % mod;
    }
    cur = next[cur][s[i] - '0'];
  }
  return cur;
}
int getdown(int x, int y) {
  for (int j = 19; j >= 0; j--)
    if (dth[jump[j][y]] > dth[x]) y = jump[j][y];
  return y;
}
int lca(int x, int y) {
  if (dth[x] < dth[y]) swap(x, y);
  int d = dth[x] - dth[y];
  for (int i = 0; i <= 19; i++)
    if (d & (1 << i)) x = jump[i][x];
  if (x == y) return x;
  for (int i = 19; i >= 0; i--)
    if (jump[i][x] != jump[i][y]) x = jump[i][x], y = jump[i][y];
  return fa[x];
}
bool check(int x, const string &sx, int y, const string &sy) {
  int lca_ = lca(x, y), lx = sx.length(), ly = sy.length();
  if (lca_ == x) {
    int tmp = getdown(lca_, y);
    int id = 0;
    while (tmp != y) {
      if (sx[id] != (wfa[tmp] + '0')) return sx[id] < wfa[tmp] + '0';
      tmp = getdown(tmp, y), ++id;
    }
    if (sx[id] != (wfa[tmp] + '0')) return sx[id] < wfa[tmp] + '0';
    ++id;
    for (int i = id; i < lx; i++)
      if (sx[i] != sy[i - id]) return sx[i] < sy[i - id];
    return 0;
  } else if (lca_ == y) {
    int tmp = getdown(lca_, x);
    int id = 0;
    while (tmp != x) {
      if (sy[id] != (wfa[tmp] + '0')) return sy[id] > wfa[tmp] + '0';
      tmp = getdown(tmp, x), ++id;
    }
    if (sy[id] != (wfa[tmp] + '0')) return sy[id] > wfa[tmp] + '0';
    ++id;
    for (int i = id; i < ly; i++)
      if (sy[i] != sx[i - id]) return sy[i] > sx[i - id];
    return 0;
  }
  int sonx = getdown(lca_, x), sony = getdown(lca_, y);
  return wfa[sonx] < wfa[sony];
}
};  // namespace Trie
using Trie::check;
struct node {
  int next, to, w, id;
  string s;
} e[maxn * 2];
int head[maxn], cnt, done[maxn];
int n, m, tot;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>>
    heap;
void adde(int x, int y, int id) {
  e[++cnt].to = y;
  e[cnt].next = head[x];
  e[cnt].id = id;
  e[cnt].s = to_string(id);
  e[cnt].w = e[cnt].s.length();
  head[x] = cnt;
}
void dij() {
  dis[1] = 0;
  heap.push({dis[1], 1});
  for (int i = 2; i <= n; i++) dis[i] = inf;
  while (heap.size()) {
    pair<int, int> cur = heap.top();
    heap.pop();
    int x = cur.second;
    if (done[x]) continue;
    done[x] = 1;
    for (int i = head[x]; i; i = e[i].next) {
      if (dis[e[i].to] > dis[x] + e[i].w) {
        dis[e[i].to] = dis[x] + e[i].w;
        heap.push({dis[e[i].to], e[i].to});
      }
    }
  }
}
bool cmp(int x, int y) { return dis[x] < dis[y]; }
int p[maxn];
void solve() {
  for (int i = 2; i <= n; i++) p[i] = i;
  sort(p + 2, p + n + 1, cmp);
  for (int i = 2; i <= n; i++) {
    int x = p[i];
    int from = -1;
    string froms = "";
    for (int j = head[x]; j; j = e[j].next) {
      if (dis[e[j].to] + e[j].w == dis[x]) {
        if (from == -1)
          from = e[j].to, froms = e[j].s;
        else {
          if (check(label[e[j].to], e[j].s, label[from], froms))
            froms = e[j].s, from = e[j].to;
        }
      }
    }
    label[x] = Trie::insert(label[from], froms);
  }
  for (int i = 2; i <= n; i++) {
    printf("%lld\n", Trie::val[label[i]]);
  }
}
int main() {
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= m; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    adde(x, y, i), adde(y, x, i);
  }
  dij();
  solve();
}
