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 <iostream>
#include <vector>
#include <algorithm>
#include <array>
#include <sstream>
using namespace std;
constexpr int siz = 51;
typedef array<long long int, siz> poly;
poly& operator +=(poly &a, const poly &b){
    for(int i=0; i<siz; i++){
        a[i] += b[i];
    }
    return a;
}
poly& operator -=(poly &a, const poly &b){
    for(int i=0; i<siz; i++){
        a[i] -= b[i];
    }
    return a;
}

template <typename T>
struct MaxFlow{
    struct edge{
        int to, rev;
        T cap;
        edge(int t, int r, T c):to(t),rev(r),cap(c){
            cap = c;
        }
        edge(){}
    };
    vector<vector<edge>> graph;
    T zero;
    T inf;
    
    MaxFlow(int n, T zero, T inf):zero(zero),inf(inf){
        graph.resize(n);
    }
    void add_edge(int from, int to, T cap){
        graph[from].emplace_back(to, graph[to].size(), cap);
        graph[to].emplace_back(from, (int)graph[from].size()-1, zero);
    }
    void add_bidirectional_edge(int from, int to, T cap){
        graph[from].emplace_back(to, graph[to].size(), cap);
        graph[to].emplace_back(from, (int)graph[from].size()-1, cap);
    }
    T dfs(int v, int g, T flow, vector<bool>& used){
        if(used[v]) return zero;
        used[v] = true;
        if(v == g) return flow;
    
        for(auto &e: graph[v]){
            if(zero < e.cap){
                T ret = dfs(e.to, g, min(flow, e.cap), used);
                if(zero < ret){
                    e.cap -= ret;
                    graph[e.to][e.rev].cap += ret;
                    return ret;
                }
            }
        }
        return zero;
    }
    T exec(int s, int g){
        T res = zero;
        while(1){
            vector<bool> used(graph.size(), false);
            T ret = dfs(s, g, inf, used);
            if(ret == zero) break;
            res += ret;
        }
        return res;
    }
};

poly str2poly(string s){
    for(char &c: s){
        if(c == '+') c = ' ';
    }
    stringstream ss(s);
    poly res{};
    string t;
    while(ss >> t){
        int n = t.length();
        int xpos = find(t.begin(), t.end(), 'x') -t.begin();
        if(xpos == n){
            res[siz-1] = stoi(t);
            continue;
        }
        int coef = 1;
        if(xpos != 0) coef = stoi(t.substr(0, xpos));
        int deg = 1;
        if(xpos != n-1) deg = stoi(t.substr(xpos+2, n-(xpos+2)));
        res[siz-1-deg] = coef;
    }
    return res;
}
string poly2str(const poly &p){
    string res = "";
    for(int i=0; i<siz; i++){
        if(p[i] == 0) continue;
        if(p[i]>0 and res!="") res += "+";
        if(i < siz-1){
            if(p[i] == -1){
                res += "-";
            }else if(p[i] != 1){
                res += to_string(p[i]);
            }
        }else{
            res += to_string(p[i]);
        }
        if(i==siz-1) continue;
        res += "x";
        if(i==siz-2) continue;
        res += "^" + to_string(siz-1-i);
    }
    if(res == "") res = "0";
    return res;
}

int main(){
    poly zero{}, inf;
    for(int i=0; i<siz; i++){
        inf[i] = 1e9;
    }
    while(1){
        int n,m;
        cin >> n >> m;
        if(n == 0) break;

        MaxFlow<poly> mf(n, zero, inf);
        for(int i=0; i<m; i++){
            int u,v;
            string s;
            cin >> u >> v >> s;
            u--; v--;
            mf.add_bidirectional_edge(u, v, str2poly(s));
        }
        poly ret = mf.exec(0, n-1);
        cout << poly2str(ret) << endl;
    }    
    return 0;
}

