#include <bits/stdc++.h>
using namespace std;
inline int read() {
  char ch = getchar();
  int x = 0, f = 1;
  while (ch < '0' || ch > '9') f = ch == '-' ? -1 : 1, ch = getchar();
  while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
  return x * f;
}
const int MAXN = 1000010;
const long long mod = 1e9 + 7;
int h[MAXN], tot = 0;
bool vis[MAXN];
long long val[MAXN];
int top;
struct edge {
  int v, w;
};
bool cmp(const edge &a, const edge &b) { return a.w < b.w; }
vector<edge> G[MAXN];
void add(int x, int y, int w) {
  if (w < 10) {
    G[x].push_back(edge{y, w});
    return;
  }
  top++;
  G[top].push_back(edge{y, w % 10});
  w /= 10;
  while (w > 9) {
    ++top;
    G[top].push_back(edge{top - 1, w % 10});
    w /= 10;
  }
  G[x].push_back(edge{top, w});
}
bool operator<(const edge &a, const edge &b) { return a.w > b.w; }
int main(int argc, char *argv[]) {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n = read(), m = read();
  top = n;
  for (int i = (1); i <= (m); i += (1)) {
    int u = read(), v = read();
    add(u, v, i), add(v, u, i);
  }
  queue<set<int> > q;
  set<int> cur, tmp[10];
  cur.insert(1);
  q.push(cur);
  vis[1] = true;
  val[1] = 0;
  while (!q.empty()) {
    cur = q.front();
    q.pop();
    int from = *cur.begin();
    for (int i = (0); i <= (9); i += (1)) tmp[i].clear();
    for (auto u : cur)
      for (auto e : G[u])
        if (!vis[e.v]) tmp[e.w].insert(e.v);
    for (int i = (0); i <= (9); i += (1)) {
      set<int> nxt;
      for (auto v : tmp[i])
        if (!vis[v]) {
          vis[v] = true;
          nxt.insert(v);
          val[v] = (val[from] * 10 + i) % mod;
        }
      if (!nxt.empty()) q.push(nxt);
    }
  }
  for (int i = (2); i <= (n); i += (1)) printf("%lld\n", val[i]);
  return 0;
}
