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 <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cassert>
using namespace std;
typedef long long ll;

#define REP(i,n) for (ll i=0; i<(ll)(n); ++i)
#define FOR(i,k,n) for (ll i=(k); i<(ll)(n); ++i)
#define FOREQ(i,k,n) for (ll i=(k); i<=(ll)(n); ++i)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define SZ(v) (ll)((v).size())
#define MEMSET(v,h) memset((v),(h),sizeof(v))

typedef ll Weight;
struct Edge {
  ll src;
  ll dest;
  Weight weight;
  Edge() {;}
  Edge(ll src, ll dest, Weight weight) : src(src), dest(dest), weight(weight) {;}
};

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

/*
   void PrllMatrix(const Matrix &mat) {
   REP(y, h) {
   REP(x, w) {
   prllf("%d ", mat[y][x]);
   }
   puts("");
   }
   }
   */

ll MaxFlow(const Graph &g, ll s, ll t, Matrix &flow) {
  const ll n = g.size();
  flow = Matrix(n, Array(n, 0));
  Matrix capacity(n, Array(n, 0));
  REP(i, n) {
    FORIT(it, g[i]) {
      capacity[it->src][it->dest] += it->weight;
    }
  }
  ll ret = 0;
  vector<ll> parent(n);
  while (true) {
    fill(parent.begin(), parent.end(), -1);
    queue<Edge> que;
    que.push(Edge(s, s, 0));
    while (!que.empty()) {
      Edge node = que.front();
      que.pop();
      if (parent[node.dest] != -1) { continue; }
      parent[node.dest] = node.src;
      if (node.dest == t) { break; }
      ll from = node.dest;
      FORIT(it, g[from]) {
        ll to = it->dest;
        if (capacity[from][to] == 0 || parent[to] != -1) { continue; }
        que.push(Edge(from, to, 0));
      }
    }
    if (parent[t] == -1) { break; }
    Weight f = 1 << 30;
    ll from = parent[t];
    ll to = t;
    while (from != to) {
      f = min(f, capacity[from][to]) ;
      from = parent[from];
      to = parent[to];
    }
    from = parent[t];
    to = t;
    while (from != to) {
      capacity[from][to] -= f;
      capacity[to][from] += f;
      flow[from][to] += f;
      flow[to][from] -= f;
      from = parent[from];
      to = parent[to];
    }
    ret += f;
  }
  return ret;
}

void AddEdge(Graph &g, ll from, ll to, ll weight) {
  if (weight == 0) { return; }
  g[from].push_back(Edge(from, to, weight));
  g[to].push_back(Edge(to, from, weight));
  cout << from << " " << to << " " << weight << endl;
}

//====================================

ll Getll(const char *str, ll &index) {
  ll ret = 1;
  if (isdigit(str[index])) {
    ret = atoi(str + index);
    while (isdigit(str[index])) { index++; }
  }
  return ret;
}

vector<ll> Parse(const char *str) {
  vector<ll> ret(52, 0);
  //ll len = strlen(str);
  ll index = 0;
  while (str[index]) {
    ll a = Getll(str, index);;
    ll degree = 0;
    if (str[index] == 'x') {
      degree = 1;
      index++;
      if (str[index] == '^') {
        index++;
        degree = Getll(str, index);
      }
    }
    if (str[index] == '+') { index++; }
    ret[degree] = a;
  }
  return ret;
}

void PrintAns(vector<ll> &ans) {
  bool first = true;
  for (ll i = 51; i >= 0; i--) {
    if (ans[i] == 0) { continue; }
    if (!first) { printf("+"); }
    first = false;
    if (i == 0) {
      printf("%lld", ans[i]);
    } else if (i >= 1) {
      if (ans[i] >= 2) {
        printf("%lld", ans[i]);
      }
      printf("x");
      if (i >= 2) {
        printf("^%lld", i);
      }
    }
  }
  if (first) {
    printf("0");
  }
  puts("");
}


const ll INF = 1 << 28;
ll n, m;
//ll u[1000];
//ll v[1000];
vector<ll> poly[60][60];
//vector<ll> poly[1000];
char str[6666];

int main() {
  while (scanf("%lld %lld", &n, &m), n|m) {
    REP(y, 60) REP(x, 60) { poly[y][x] = vector<ll>(52, 0); }
    REP(i, m) {
      ll u, v;
      scanf("%lld %lld %s", &u, &v, str);
      u--; v--;
      vector<ll> p = Parse(str);
      REP(j, 51) {
        poly[u][v][j] += p[j];
        poly[v][u][j] += p[j];
      }
    }
    vector<ll> ans(52, 0);
    for (ll i = 51; i >= 0; i--) {
      Graph g(n);
      REP(y, n) {
        REP(x, n) {
          if (poly[y][x][i] == 0) { continue; }
          g[y].push_back(Edge(y, x, poly[y][x][i]));
        }
      }
      Matrix flow;
      ans[i] = MaxFlow(g, 0, n - 1, flow);
      if (i != 0) {
        REP(y, n) {
          REP(x, n) {
            if (poly[y][x][i] - flow[y][x] == 0) { continue; }
            if (poly[y][x][i] + flow[y][x] == 0) { continue; }
            poly[y][x][i - 1] = INF;
          }
        }
      }
    }
    PrintAns(ans);
  }
}