The trafic on the Internet is increasing these days due to smartphones. The wireless carriers have to enhance their network infrastructure.

The network of a wireless carrier consists of a number of base stations and lines. Each line connects two base stations bi-directionally. The bandwidth of a line increases every year and is given by a polynomial f(x) of the year x.

Your task is, given the network structure, to write a program to calculate the maximal bandwidth between the 1-st and N-th base stations as a polynomial of x.



Input

The input consists of multiple datasets. Each dataset has the following format:

N M
u1 v1 p1
...
uM vM pM


The first line of each dataset contains two integers N (2 ≤ N ≤ 50) and M (0 ≤ M ≤ 500), which indicates the number of base stations and lines respectively. The following M lines describe the network structure. The i-th of them corresponds to the i-th network line and contains two integers ui and vi and a polynomial pi. ui and vi indicate the indices of base stations (1 ≤ ui, vi ≤ N); pi indicates the network bandwidth.

Each polynomial has the form of:

aLxL + aL-1xL-1 + ... + a2x2 + a1x + a0

where L (0 ≤ L ≤ 50) is the degree and ai's (0 ≤ i ≤ L, 0 ≤ ai ≤ 100) are the coefficients. In the input,

* each term aixi (for i ≥ 2) is represented as <ai>x^<i>
* the linear term (a1x) is represented as <a1>x;
* the constant (a0) is represented just by digits;
* these terms are given in the strictly decreasing order of the degrees and connected by a plus sign ("+");
* just like the standard notations, the <ai> is omitted if ai = 1 for non-constant terms;
* similarly, the entire term is omitted if ai = 0 for any terms; and
* the polynomial representations contain no space or characters other than digits, "x", "^", and "+".



For example, 2x2 + 3x + 5 is represented as 2x^2+3x+5; 2x3 + x is represented as 2x^3+x, not 2x^3+0x^2+1x+0 or the like. No polynomial is a constant zero, i.e. the one with all the coefficients being zero.

The end of input is indicated by a line with two zeros. This line is not part of any dataset.

Output

For each dataset, print the maximal bandwidth as a polynomial of x. The polynomial should be represented in the same way as the input format except that a constant zero is possible and should be represented by "0" (without quotes).

Example

Input

3 3
1 2 x+2
2 3 2x+1
3 1 x+1
2 0
3 2
1 2 x
2 3 2
4 3
1 2 x^3+2x^2+3x+4
2 3 x^2+2x+3
3 4 x+2
0 0


Output

2x+3
0
2
x+2
#include <bits/stdc++.h>
using namespace std;
 
const int INF = 1<<28;
const int L = 51;
 
struct Edge {
  int to, cost, rev;
  vector<int> cap;
  Edge(int to, int cost, vector<int> cap, int rev)
    : to(to), cost(cost), cap(cap), rev(rev) {}
  Edge() {}
};
 
typedef vector<vector<Edge> > Graph;
 
void addEdgeF(int from, int to, int cost, vector<int> cap, Graph &g) {
  g[from].push_back(Edge(to, cost, cap, g[to].size()));
  g[to].push_back(Edge(from, -cost, vector<int>(L), (int)g[from].size()-1));
}
 
inline void add(vector<int> &a, const vector<int> &b) {
  for(int i = 0; i < L; ++i) a[i] += b[i];
}
 
inline void subtract(vector<int> &a, const vector<int> &b) {
  for(int i = 0; i < L; ++i) a[i] -= b[i];
}
 
inline bool lt(const vector<int> &a, const vector<int> &b) {
  for(int i = L-1; i >= 0; --i) if(a[i] != b[i]) return a[i] < b[i];
  return false;
}
 
inline bool le(const vector<int> &a, const vector<int> &b) {
  for(int i = L-1; i >= 0; --i) if(a[i] != b[i]) return a[i] < b[i];
  return true;
}
 
void show(const vector<int> &ans) {
  if(*max_element(ans.begin(), ans.end()) == 0 &&
     *min_element(ans.begin(), ans.end()) == 0) {
    cout << 0 << endl;
    return;
  }
  for(int i = L-1, j = 0; i >= 0; --i) {
    if(!ans[i]) continue;
    if(j) {
      if(ans[i] > 0) cout << "+";
      else cout << "-";
    } else if(ans[i] < 0) cout << "-";
    if(i == 0) {
      cout << abs(ans[i]);
    } else {
      if(abs(ans[i]) != 1) cout << abs(ans[i]);
      if(i > 1) cout << "x^" << i;
      else if(i == 1) cout << "x";
    }
    j++;
  }
  cout << endl;
}

void bfs(int s, vector<int> &level, Graph &g) {
  int n = g.size();
  level = vector<int>(n, -1);
  queue<int> que;
  level[s] = 0;
  que.push(s);
  while(!que.empty()) {
    int v = que.front(); que.pop();
    for(int i = 0; i < g[v].size(); ++i) {
      const Edge &e = g[v][i];
      if(level[e.to] < 0 && lt(vector<int>(L), e.cap)) {
        level[e.to] = level[v] + 1;
        que.push(e.to);
      }
    }
  }
}

vector<int> dfs(int v, int t, vector<int> f, vector<int> &level, vector<int> &iter, Graph &g) {
  if(v == t) return f;
  for(int &i = iter[v]; i < g[v].size(); ++i) {
    Edge &e = g[v][i];
    if(level[v] < level[e.to] && lt(vector<int>(L), e.cap)) {
      vector<int> d = dfs(e.to, t, lt(f, e.cap) ? f : e.cap, level, iter, g);
      if(lt(vector<int>(L), d)) {
        subtract(e.cap, d);
        add(g[e.to][e.rev].cap, d);
        return d;
      }
    }
  }
  return vector<int>(L);
}

vector<int> maxFlow(int s, int t, Graph g) {
  vector<int> flow(L);
  while(1) {
    vector<int> level;
    bfs(s, level, g);
    if(level[t] < 0) return flow;
    vector<int> iter(g.size());
    vector<int> f;
    while(lt(vector<int>(L), f = dfs(s, t, vector<int>(L, INF), level, iter, g))) {
      add(flow, f);
    }
  }
  return flow;
}
 
int main() {
  for(int N, M; cin >> N >> M && (N|M); ) {
    Graph g(N);
    for(int i = 0; i < M; ++i) {
      int u, v; cin >> u >> v; --u; --v;
      string s; cin >> s;
      vector<int> cap(L);
      replace(s.begin(), s.end(), '+', ' ');
      stringstream ss(s);
      while(ss >> s) {
        int a = 1;
        {
          int i = 0;
          while(i < s.size() && isdigit(s[i])) ++i;
          if(i) {
            a = atoi(s.substr(0, i).c_str());
            s = s.substr(i);
          }
        }
        int k = 0;
        // "" or "x" or "x^y"
        if(s == "x") {
          k = 1;
        } else if(s.size()) {
          k = atoi(s.substr(2).c_str());
        }
        cap[k] = a;
      }
      addEdgeF(u, v, 0, cap, g);
      addEdgeF(v, u, 0, cap, g);
    }
    show(maxFlow(0, N-1, g));
  }
  return 0;
}