#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,n) for(ll i=0;i<(ll)n;i++)

string S1,S2,S3;
vector<char> chars;
char used[10];

bool check() {
    map<char, char> mp;
    rep(i,10) if (used[i] != 0) mp[used[i]] = char('0' + i);

    string s1,s2,s3;
    for(auto &c: S1) s1 += mp[c];
    for(auto &c: S2) s2 += mp[c];
    for(auto &c: S3) s3 += mp[c];

    if(to_string(stoll(s1)) != s1) return false;
    if(to_string(stoll(s2)) != s2) return false;
    if(to_string(stoll(s3)) != s3) return false;
    if(stoll(s1) + stoll(s2) != stoll(s3)) return false;
    if(stoll(s1) == 0) return false;
    if(stoll(s2) == 0) return false;
    if(stoll(s3) == 0) return false;

    cout << s1 << endl;
    cout << s2 << endl;
    cout << s3 << endl;
    return true;
}

bool dfs(int di) {
    if (di == chars.size()) return check();
    rep(i,10) {
        if (used[i] == 0) {
            used[i] = chars[di];
            if (dfs(di + 1)) return true;
            used[i] = 0;
        }
    }
    return false;
}


int main() {
    cin >> S1 >> S2 >> S3;
    rep(i,S1.size()) chars.push_back(S1[i]);
    rep(i,S2.size()) chars.push_back(S2[i]);
    rep(i,S3.size()) chars.push_back(S3[i]);
    sort(chars.begin(),chars.end());
    chars.erase(unique(chars.begin(),chars.end()), chars.end());
    
    if (chars.size() > 10) {
        cout << "UNSOLVABLE" << endl;
        return 0;
    }

    bool ans = dfs(0);
    if(ans == false) cout << "UNSOLVABLE" << endl; 
}
// give up
#include <bitset>
#include <iostream>
#include <iomanip>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>

// alias, using declaration
using llint = long long; using ldouble = long double;
template <class T = llint> using vector = std::vector<T>;
template <class T = llint> using deque = std::deque<T>;
template <class T = llint, class U = llint, class... V> using map = std::map<T, U, V...>;
template <class T = llint, class... U> using set = std::set<T, U...>;
template <class T = llint, class U = llint> using umap = std::unordered_map<T, U>;
template <class T = llint> using uset = std::unordered_set<T>;
template <class T = llint, class U = T> using pair = std::pair<T, U>;
template <class T = llint> using varray = std::valarray<T>;
template <class T = llint, class... U> using pqueue = std::priority_queue<T, U...>;
using std::array; using std::bitset; using std::string; using std::tuple;

// constant
constexpr llint INF = 0x3FFFFFFFFFFFFFFF;
constexpr llint INVALID = 0x8000000000000000;

namespace io {
  // in
  template <class... T, size_t... S> auto in(std::index_sequence<S...>) {tuple<T...> t; (..., (std::cin >> std::get<S>(t))); return t;}
  template <class... T, size_t... S> auto in(std::index_sequence<S...>, size_t n) {tuple<vector<T>...> t{vector<T>(n)...}; for (size_t i = 0; i < n; i++) (..., (std::cin >> std::get<S>(t)[i])); return t;}
  template <size_t N, class T = llint, class... U> auto in() {static_assert(N >= 1); if constexpr (N > 1) return in<N - 1, T, T, U...>(); else return in<T, U...>(std::index_sequence_for<T, U...>());}
  template <size_t N, class T = llint, class... U> auto in(size_t n) {static_assert(N >= 1); if constexpr (N > 1) return in<N - 1, T, T, U...>(n); else return in<T, U...>(std::index_sequence_for<T, U...>(), n);}
  template <size_t N, class T = llint> auto in(size_t n, size_t m) {static_assert(N == 1); vector<vector<T>> v(n, vector<T>(m)); for (auto&& vi : v) for (auto&& vij : vi) std::cin >> vij; return std::make_tuple(v);}
  // out
  template <class T, class... U> void out(const T& a, const U&... b) {std::cout << a << (sizeof...(b) ? " " : "\n"); if constexpr (sizeof...(b)) out(b...);}
  template <class T, class U = const char*> void out(const vector<T>& a, U d = " ") {for (auto&& b : a) std::cout << b << (&b != &a.back() ? d : "\n");}
}

int main() {
  // input
  auto [N, M] = io::in<2>();
  auto [A, B] = io::in<2>(M);

  // solve
  vector<vector<>> graph(N);
  for (llint i = 0; i < M; i++) {
    graph[A[i] - 1].emplace_back(B[i] - 1);
    graph[B[i] - 1].emplace_back(A[i] - 1);
  }
  vector<bool> visited(N);
  vector<vector<>> s;
  auto dfs_s = [&](auto f, llint n) -> void {
    visited[n] = true;
    s.back().emplace_back(n);
    for (auto g : graph[n]) {
      if (!visited[g]) {
        f(f, g);
      }
    }
  };
  for (llint i = 0; i < N; i++) {
    if (!visited[i]) {
      s.emplace_back();
      dfs_s(dfs_s, i);
    }
  }
  vector<> color(N, INVALID);
  auto result = 1LL;
  auto dfs_p = [&](auto f, auto b, auto e, llint c) -> llint {
    for (auto g : graph[*b]) {
      if (color[g] == c) return 0;
    }
    auto bn = std::next(b);
    if (bn == e) return 1;
    color[*b] = c;
    llint r = f(f, bn, e, 0) + f(f, bn, e, 1) + f(f, bn, e, 2);
    color[*b] = INVALID;
    return r;
  };
  for (auto t : s) {
    result *= dfs_p(dfs_p, t.begin(), t.end(), 0) * 3;
  }

  // output
  io::out(result);
}