Problem:
Problem I:
Mobile Network
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
u
1
v
1
p
1
...
u
M
v
M
p
M
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
u
i
and
v
i
and a polynomial
p
i
.
u
i
and
v
i
indicate the indices of base stations (1 ≤
u
i
,
v
i
≤
N
);
p
i
indicates the network bandwidth.
Each polynomial has the form of:
a
L
x
L
+
a
L
-1
x
L
-1
+ ... +
a
2
x
2
+
a
1
x
+
a
0
where
L
(0 ≤
L
≤ 50) is the degree and
a
i
's (0 ≤
i
≤
L
, 0 ≤
a
i
≤ 100) are the coefficients. In the input,
each term
a
i
x
i
(for
i
≥ 2) is represented as <
a
i
>
x
^<
i
>
the linear term (
a
1
x
) is represented as <
a
1
>
x
;
the constant (
a
0
) 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 <
a
i
> is omitted if
a
i
= 1 for non-constant terms;
similarly, the entire term is omitted if
a
i
= 0 for any terms; and
the polynomial representations contain no space or characters other than digits, "x", "^", and "+".
For example, 2
x
2
+ 3
x
+ 5 is represented as
2x^2+3x+5
; 2
x
3
+
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).
Sample 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 for the Sample Input
2x+3
0
2
x+2

Submitted solutions:

code_snippet: #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <algorithm>
#include <vector>
#include <list>
#include <deque>

#define LL long long
#define DB double
#define SI(a) scanf("%d",&a)
#define SD(a) scanf("%lf",&a)
#define SS(a) scanf("%s",a)
#define PF printf
#define MM(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REPD(i,a,b) for(int i=a;i>b;i--)
#define INF 0x3f3f3f3f
#define EPS 1e-8
#define bug puts("bug")
using namespace std;
const int N = 55;
int re[N][N][55];
int res[N][N];
int n,m;
void ini()
{
    MM(re,0);
    MM(res,0);
}
void oper_i(char a[],int &e,int &f)
{
    int flag = 0,flag1 = 0;
    int len = strlen(a);
    REP(i,0,len)
    {
        if(a[i]=='x')
            flag = 1;
        if(a[i]=='^')
            flag1 = 1;
    }
    if(flag == 0)
    {
        e = 0;
        sscanf(a,"%d",&f);
        return;
    }
    if(flag1 == 1)
    {
        if(a[0]=='x')
        {
            f = 1;
            sscanf(a,"x^%d",&e);
            return;
        }
        sscanf(a,"%dx^%d",&f,&e);
        return;
    }else
    {
        if(a[0]=='x')
        {
            f = 1;e = 1;
            return;
        }
        sscanf(a,"%dx",&f);
        e = 1;
        return;
    }
}
void oper(char ch[],int c[])//
{
    REP(i,0,51) c[i] = 0;
    char tmp[50];
    int j=0,len = strlen(ch);
    int e,f;
    REP(i,0,len+1)
    {
        if(ch[i]=='+'||ch[i]=='\0'||ch[i]=='\n')
        {
            tmp[j] = '\0';
            oper_i(tmp,e,f);
            //cout<<f<<"^"<<e<<endl;
            c[e] += f;
            j = 0;
        }else
        {
            tmp[j] = ch[i];
            j++;
        }
    }
}

int g[N][N],gap[N],dist[N],pre[N],cur[N];
///s1->t1 size{1...n}
int sap(int s1,int t1,int n)
{
    int ret = 0,aug = INF,u,v;
    memset(gap,0,sizeof(gap));
    memset(dist,0,sizeof(dist));
    for(int i=0;i<=n;i++) cur[i] = 1;
    u = pre[s1] = s1;
    gap[0] = n;
    while(dist[s1]<=n){
    loop:
        for(v = cur[u];v<=n;v++)
        if(g[u][v]>0&&dist[u] ==dist[v]+1)
        {
            cur[u] = v;aug = min(aug,g[u][v]);
            pre[v] = u;
            u = v;
            if(u==t1){
                ret+=aug;
                for(u=pre[u];v!=s1;v=u,u=pre[u])
                g[u][v]-=aug,g[v][u]+=aug;
                aug = INF;
            }
            goto loop;
        }
        int mind =n;
        for(v=1;v<=n;v++)
        	if(g[u][v]>0&&mind>dist[v])
        	mind = dist[v],cur[u] = v;
        if(--gap[dist[u]]<=0) break;
        gap[dist[u]=mind+1]++;
        u=pre[u];
    }return ret;
}
void solve()
{
    int ans[109];
    MM(ans,0);
    REPD(t,50,-1)
    {
        REP(i,1,n+1)
        REP(j,1,n+1)
        {
            if(res[i][j])
                g[i][j] = INF;
            else
                g[i][j] = re[i][j][t];
        }
        ans[t] = sap(1,n,n);
        //if(ans[t]>0)
        //cout<<t<<" "<<ans[t]<<endl;
        REP(i,1,n+1)
        REP(j,1,n+1)
        if(res[i][j]==0&&re[i][j][t])
        {
            if(g[i][j]>0)
            {
                res[i][j] = 1;
                //cout<<i<<"---"<<j<<endl;
            }
            else
            {
                REP(k,1,n+1)
                REP(l,1,n+1)
                {
                    if(res[k][l])
                        g[k][l] = INF;
                    else
                        g[k][l] = re[k][l][t];
                }
                g[i][j] -= 1;
                if(ans[t]==sap(1,n,n))
                {
                    res[i][j] = 1;
                    //cout<<i<<"---"<<j<<endl;
                }
            }
        }
    }

    int flag = 0;
    REPD(i,50,-1)
    {
        if(ans[i])
        {
            if(flag) printf("+");
            flag = 1;
            if(i>1)
            {
                if(ans[i]==1)
                    printf("x^%d",i);
                else
                    printf("%dx^%d",ans[i],i);
            }else if(i==1)
            {
                if(ans[i]==1)
                    printf("x");
                else
                    printf("%dx",ans[i]);
            }else
            {
                printf("%d",ans[i]);
            }
        }
    }
    if(flag==0) printf("0");
    printf("\n");
}
int main()
{
    #ifndef ONLINE_JUDGE
    //freopen("in.txt","r",stdin);
    #endif
    int tmp[100];
    while(1)
    {
        SI(n),SI(m);
        if(n==0&&m==0) break;
        ini();

        int a,b;
        char ch[1024];
        REP(i,0,m)
        {
            SI(a),SI(b);
            SS(ch);
            oper(ch,tmp);
            REP(j,0,51)
            if(tmp[j])
            {
                re[a][b][j]+=tmp[j];
                re[b][a][j]+=tmp[j];
            }
        }
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 3992
final_rank: 6

code_snippet: #include <bits/stdc++.h>

template <class T>
T inf() {
    return std::numeric_limits<T>::max();
}

template <class T>
T calc_next_flow(const T& lhs, const T& rhs) {
    return std::min(lhs, rhs);
}

struct Poly {
    static constexpr int D = 50;
    static constexpr int MAX_COEF = 100;

    std::array<int, D + 1> coef = {};

    Poly() {}
    Poly(int coe, int deg) {
        coef[deg] = coe;
    }

    int dim() const {
        for (int i = D; i >= 0; i--) {
            if (coef[i] != 0) return i;
        }
        return -1;
    }

    friend std::ostream& operator<<(std::ostream& os, const Poly& poly) {
        std::string expr;
        int dim = poly.dim();
        for (int i = dim; i >= 0; --i) {
            if (poly.coef[i] == 0) continue;

            if (i != dim) expr.push_back('+');
            if (poly.coef[i] != 1 || i == 0) {
                expr += std::to_string(poly.coef[i]);
            }

            if (i != 0) {
                expr.push_back('x');
                if (i != 1) {
                    expr.push_back('^');
                    expr += std::to_string(i);
                }
            }
        }
        if (dim == -1) {
            expr.push_back('0');
        }

        os << expr;
        return os;
    }

    friend bool operator==(const Poly& lhs, const Poly& rhs) {
        for (int i = 0; i <= D; i++) {
            if (lhs.coef[i] != rhs.coef[i]) return false;
        }
        return true;
    }

    friend bool operator!=(const Poly& lhs, const Poly& rhs) {
        return !(lhs == rhs);
    }

    friend Poly operator+(const Poly& lhs, const Poly& rhs) {
        return Poly(lhs) += rhs;
    }

    friend Poly operator-(const Poly& lhs, const Poly& rhs) {
        return Poly(lhs) -= rhs;
    }

    Poly& operator+=(const Poly& other) {
        for (int i = 0; i <= D; i++) {
            this->coef[i] += other.coef[i];
        }
        return *this;
    }

    Poly& operator-=(const Poly& other) {
        for (int i = 0; i <= D; i++) {
            this->coef[i] -= other.coef[i];
        }
        return *this;
    }
};

template <>
Poly inf<Poly>() {
    Poly res;
    res.coef.fill(Poly::MAX_COEF);
    return res;
}

template <>
Poly calc_next_flow<Poly>(const Poly& lhs, const Poly& rhs) {
    for (int i = Poly::D; i >= 0; i--) {
        if (lhs.coef[i] < rhs.coef[i]) {
            return lhs;
        } else if (lhs.coef[i] > rhs.coef[i]) {
            return rhs;
        }
    }
    return lhs;
}


template <class Flow>
struct MaxFlow {
    struct Edge {
        int to;
        int rev;
        Flow flow;
        Flow cap;

        Edge(int to, int rev, const Flow& flow, const Flow& cap)
            : to(to), rev(rev), flow(flow), cap(cap) {}
    };

    int n;
    std::vector<std::vector<Edge>> graph;
    std::vector<int> label;
    std::vector<int> index;

    MaxFlow(int n): n(n), graph(n), label(n), index(n) {}

    void add_edge(int u, int v, const Flow& cap) {
        assert(0 <= u && u < n);
        assert(0 <= v && v < n);
        int i = graph[u].size();
        int j = graph[v].size();
        graph[u].emplace_back(v, j, Flow(), cap);
        graph[v].emplace_back(u, i, cap, cap);
    }

    Flow flow(int source, int sink) {
        Flow res{};
        while (true) {
            bfs(source);
            index.assign(n, 0);
            auto diff = dfs(source, sink, inf<Flow>());
            if (diff == Flow()) break;
            res += diff;
        }
        return res;
    }

    void bfs(int source) {
        std::queue<int> que;
        label.assign(n, -1);
        label[source] = 0;
        que.push(source);
        while (!que.empty()) {
            int u = que.front();
            que.pop();
            for (const auto& e: graph[u]) {
                if (label[e.to] == -1 && e.flow != e.cap) {
                    label[e.to] = label[u] + 1;
                    que.push(e.to);
                }
            }
        }
    }

    Flow dfs(int u, int sink, Flow cur_flow) {
        if (cur_flow == Flow()) return cur_flow;
        if (u == sink) return cur_flow;

        Flow res{};
        for (int& i = index[u]; i < (int)graph[u].size(); i++) {
            auto& e = graph[u][i];
            auto v = e.to;
            if (label[v] != label[u] + 1) continue;

            auto next_flow = calc_next_flow(cur_flow, e.cap - e.flow);
            auto diff = dfs(v, sink, next_flow);

            if (diff != Flow()) {
                res += diff;
                e.flow += diff;
                cur_flow -= diff;
                graph[v][e.rev].flow -= diff;
                if (cur_flow == Flow()) break;
            }
        }
        return res;
    }
};

struct Parser {
    using CopyIter = std::string::const_iterator;
    using Iter = CopyIter&;
    std::string line;
    Parser() {}

    void skip(Iter it, char c) {
        assert(*it == c);
        ++it;
    }

    Poly parse(const std::string& s) {
        line = s;
        auto it = line.cbegin();
        return expr(it);
    }

    Poly expr(Iter it) { 
        auto res = term(it);
        while (it != line.end() && *it == '+') {
            skip(it, '+');
            res += term(it);
        }
        return res;
    }

    Poly term(Iter it) {
        auto coef = number(it);
        auto deg = degree(it);
        return Poly(coef, deg);
    }

    int number(Iter it) {
        int res = 0;
        while (it != line.end() && std::isdigit(*it)) {
            res = 10 * res + *it - '0';
            ++it;
        }
        if (res == 0) res = 1;
        return res;
    }

    int degree(Iter it) {
        if (it == line.end() || *it != 'x') return 0;
        skip(it, 'x');
        if (it == line.end() || *it != '^') return 1;
        skip(it, '^');
        return number(it);
    }
};

void flow_test() {
    MaxFlow<int> graph(4);
    graph.add_edge(0, 1, 5);
    graph.add_edge(0, 2, 2);
    graph.add_edge(1, 3, 1);
    graph.add_edge(2, 3, 3);
    std::cerr << graph.flow(0, 3) << std::endl;
}

void parser_test() {
    std::vector<std::string> tests {
        "x+2",
        "2x+1",
        "x+1",
        "x",
        "2",
        "x^3+2x^2+3x+4",
        "x^2+2x+3",
    };

    Parser parser;

    for (auto test: tests) {
        std::cerr << test << ' ' << parser.parse(test) << std::endl;
    }
}

int main() {
    // parser_test();
    // return 0;

    Parser parser;
    while (true) {
        int n, m;
        std::cin >> n >> m;
        if (n == 0 && m == 0) break;
        MaxFlow<Poly> graph(n);
        const int source = 0;
        const int sink = n - 1;
        for (int i = 0; i < m; i++) {
            int u, v;
            std::string formula;
            std::cin >> u >> v >> formula;
            u--; v--;
            auto poly = parser.parse(formula);
            graph.add_edge(u, v, poly);
            graph.add_edge(v, u, poly);
        }
        auto ans = graph.flow(source, sink);
        std::cout << ans << std::endl;
    }
}
accuracy: 1
time_ms: 50
memory_kb: 4480
final_rank: 7

code_snippet: #include<iostream>
#include<vector>
#include<array>
using namespace std;
//Dinic O(EV^2)
#include<algorithm>
#include<utility>
#include<vector>
#include<queue>
#include<limits>
template<typename T>
struct MF{
	struct edge{
		int to,rev;
		T cap;
	};
	vector<vector<edge> >G;
	vector<int>level,iter;
	MF(int n_=0):G(n_),level(n_),iter(n_){}
	int add_edge(int from,int to,T cap)
	{
		G[from].push_back({to,(int)G[to].size(),cap});
		G[to].push_back({from,(int)G[from].size()-1,0});
		return G[from].size()-1;
	}
	T dfs(int u,int t,T f)
	{
		if(u==t)return f;
		for(;iter[u]<G[u].size();iter[u]++)
		{
			edge&e=G[u][iter[u]];
			if(e.cap>0&&level[u]<level[e.to])
			{
				T d=dfs(e.to,t,min(f,e.cap));
				if(d>0)
				{
					e.cap-=d;
					G[e.to][e.rev].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	T max_flow(int s,int t)
	{
		T ret=0;
		for(;;)
		{
			fill(level.begin(),level.end(),-1);
			queue<int>P;
			level[s]=0;
			P.push(s);
			while(!P.empty())
			{
				int u=P.front();P.pop();
				for(edge&e:G[u])
				{
					if(e.cap>0&&level[e.to]<0)
					{
						level[e.to]=level[u]+1;
						P.push(e.to);
					}
				}
			}
			if(level[t]<0)return ret;
			fill(iter.begin(),iter.end(),0);
			for(T f;(f=dfs(s,t,numeric_limits<T>::max()))>0;)ret+=f;
		}
	}
};
int N,M;
array<int,51>parse()
{
	string s;cin>>s;
	array<int,51>ret;
	for(int i=0;i<=50;i++)ret[i]=0;
	for(int i=0;i<s.size();)
	{
		int coef=1;
		if(isdigit(s[i]))
		{
			coef=0;
			while(isdigit(s[i]))coef=coef*10+s[i++]-'0';
		}
		int dim=0;
		if(i<s.size())
		{
			if(s[i++]!='x')cout<<"ERROR"<<endl;
			if(i<s.size()&&s[i]=='^')
			{
				i++;
				while(isdigit(s[i]))dim=dim*10+s[i++]-'0';
			}
			else dim=1;
		}
		ret[dim]=coef;
		i++;
	}
	return ret;
}
main()
{
	while(cin>>N>>M,N)
	{
		vector<vector<pair<int,array<int,51> > > >G(N);
		for(int i=0;i<M;i++)
		{
			int u,v;cin>>u>>v;u--,v--;
			array<int,51>p=parse();
			G[u].push_back(make_pair(v,p));
			G[v].push_back(make_pair(u,p));
		}
		bool fst=true;
		for(int dim=50;dim>=0;dim--)
		{
			MF<int>P(N);
			vector<vector<int> >ei(N);
			for(int i=0;i<N;i++)
			{
				for(pair<int,array<int,51> >e:G[i])
				{
					ei[i].push_back(P.add_edge(i,e.first,e.second[dim]));
				}
			}
			int ans=P.max_flow(0,N-1);
			if(ans!=0)
			{
				if(!fst)cout<<"+";
				else fst=false;
				if(dim==0||ans!=1)cout<<ans;
				if(dim>0)
				{
					cout<<"x";
					if(dim>1)cout<<"^"<<dim;
				}
			}
			if(dim>0)
			{
				for(int i=0;i<N;i++)
				{
					for(int j=0;j<ei[i].size();j++)
					{
						if(P.G[i][ei[i][j]].cap>0)G[i][j].second[dim-1]+=1e5;
					}
				}
			}
		}
		if(fst)cout<<"0";
		cout<<endl;
	}
}
accuracy: 1
time_ms: 140
memory_kb: 3404
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())

const int mod=1000000007,MAX=1003,INF=1<<30;

struct edge{
    int to;
    vector<int> cap;
    int rev;
};

vector<edge> G[MAX];
int level[MAX];
int iter[MAX];

void add(vector<int> &a,vector<int> &b,bool f){
    while(si(a)<si(b)) a.push_back(0);
    for(int i=0;i<min(si(a),si(b));i++){
        if(f) a[i]+=b[i];
        else a[i]-=b[i];
    }
    while(si(a)&&a.back()==0) a.pop_back();
}

vector<int> mi(vector<int> &a,vector<int> &b){
    
    for(int i=max(si(a),si(b))-1;i>=0;i--){
        int x,y;
        if(i<si(a)) x=a[i];
        else x=0;
        
        if(i<si(b)) y=b[i];
        else y=0;
        
        if(x!=y){
            if(x<y) return a;
            else return b;
        }
    }
    return b;
}

void add_edge(int from,int to,vector<int> cap){
    G[from].push_back((edge){to,cap,int(G[to].size())});
    G[to].push_back((edge){from,{},int(G[from].size())-1});
}

void BFS(int s){
    memset(level,-1,sizeof(level));
    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++){
            edge &e =G[v][i];
            if(si(e.cap)&&level[e.to]<0){
                level[e.to]=level[v]+1;
                que.push(e.to);
            }
        }
    }
}

vector<int> DFS(int v,int t,vector<int> f){
    if(v==t) return f;
    for(int &i=iter[v];i<G[v].size();i++){
        edge &e =G[v][i];
        if(si(e.cap)&&level[v]<level[e.to]){
            auto d= DFS(e.to,t,mi(f,e.cap));
            if(si(d)){
                add(e.cap,d,0);
                add(G[e.to][e.rev].cap,d,1);
                return d;
            }
        }
    }
    return {};
}

vector<int> max_flow(int s,int t){
    vector<int> flow={};
    for(;;){
        BFS(s);
        if(level[t]<0) return flow;
        memset(iter,0,sizeof(iter));
        vector<int> f={};
        while(si((f = DFS(s, t, vector<int>(51, INF))))){
            add(flow,f,1);
        }
    }
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        int N,M;cin>>N>>M;
        if(N==0&&M==0) break;
        
        for(int i=0;i<MAX;i++){
            G[i].clear();
            level[i]=0;
            iter[i]=0;
        }
        
        for(int i=0;i<M;i++){
            int a,b;string S;cin>>a>>b>>S;
            a--;b--;
            vector<int> d;
            
            bool xaru=false;
            for(char c:S) if(c=='x') xaru=true;
            
            if(xaru){
                int deg=0;
                int j=0;
                while(j<si(S)&&S[j]!='^') j++;
                j++;
                while(j<si(S)&&isdigit(S[j])){
                    deg*=10;
                    deg+=S[j]-'0';
                    j++;
                }
                if(deg==0) deg=1;
                d.resize(deg+1);
                
                j=0;
                while(j<si(S)){
                    int a=0,b=0;
                    while(isdigit(S[j])){
                        a*=10;
                        a+=S[j]-'0';
                        j++;
                    }
                    if(a==0) a=1;
                    if(j==si(S)){
                        d[b]=a;
                        break;
                    }
                    j++;
                    if(S[j]=='^'){
                        j++;
                        while(j<si(S)&&isdigit(S[j])){
                            b*=10;
                            b+=S[j]-'0';
                            j++;
                        }
                        d[b]=a;
                        j++;
                    }else{
                        j++;
                        d[1]=a;
                    }
                }
            }else{
                d.push_back(stoi(S));
            }
            
            //for(int a:d) cout<<a<<" ";
            //cout<<endl;
            
            add_edge(a,b,d);
            add_edge(b,a,d);
        }
        
        auto f=max_flow(0,N-1);
        
        bool de=false;
        for(int i=si(f)-1;i>=0;i--){
            if(f[i]==0) continue;
            if(de) cout<<"+";
            de=true;
            
            if(f[i]>1||i==0) cout<<f[i];
            if(i) cout<<"x";
            if(i>=2) cout<<"^"<<i;
        }
        
        if(!de) cout<<0;
        cout<<endl;
        
        //for(int a:f) cout<<a<<" ";
        //cout<<endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3832
final_rank: 4

code_snippet: #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;
}
accuracy: 1
time_ms: 4990
memory_kb: 3880
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <array>
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(const string &s){
    poly res{};
    int n = s.length();
    for(int i=0; i<n;){
        int coef = 1;
        if(s[i] == '+') i++;
        if('0'<=s[i] and s[i]<='9'){
            coef = 0;
            while('0'<=s[i] and s[i]<='9'){
                coef *= 10;
                coef += s[i]-'0';
                i++;
            }
        }
        if(i == n){
            res[siz-1] += coef;
            break;
        }
        i++;
        if(i==n or s[i]!='^'){
            i++;
            res[siz-2] += coef;
            continue;
        }
        i++;
        int exp = 0;
        while('0'<=s[i] and s[i]<='9'){
            exp *= 10;
            exp += s[i]-'0';
            i++;
        }
        res[siz-1-exp] += 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){
            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 += "^";
        res += to_string(siz-1-i);
    }
    if(res == ""){
        res = "0";
    }
    if(res[0] == '+'){
        res.erase(res.begin());
    }
    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;
}
accuracy: 1
time_ms: 4910
memory_kb: 3876
final_rank: 9

code_snippet: #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2328"

#include<bits/stdc++.h>
using namespace std;

#define call_from_test
#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
struct FastIO{
  FastIO(){
    cin.tie(0);
    ios::sync_with_stdio(0);
  }
}fastio_beet;
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
vector<string> split(string& s,char c){
  int n=s.size();
  vector<string> res;
  for(int i=0;i<n;i++){
    if(s[i]==c) continue;
    string t;
    while(i<n&&s[i]!=c) t.push_back(s[i++]);
    res.push_back(t);
  }
  return res;
}
//END CUT HERE
#ifndef call_from_test
signed YUKI_932(){
  string s;
  cin>>s;
  auto ss=split(s,',');
  cout<<(ss==vector<string>(ss.size(),"AC")?"Done!":"Failed...")<<endl;
  return 0;
}
/*
  verified 2019/11/30
  https://yukicoder.me/problems/no/932
*/

signed main(){
  YUKI_932();
  return 0;
}
#endif

#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
using Int = long long;
#endif
//BEGIN CUT HERE
template<typename T,bool directed>
struct Dinic{
  struct edge {
    int to;
    T cap;
    int rev;
    edge(){}
    edge(int to,T cap,int rev):to(to),cap(cap),rev(rev){}
  };

  vector<vector<edge> > G;
  vector<int> level,iter;

  Dinic(){}
  Dinic(int n):G(n),level(n),iter(n){}

  int add_edge(int from,int to,T cap){
    G[from].emplace_back(to,cap,G[to].size());
    G[to].emplace_back(from,directed?0:cap,G[from].size()-1);
    return G[to].back().rev;
  }

  void bfs(int s){
    fill(level.begin(),level.end(),-1);
    queue<int> que;
    level[s]=0;
    que.emplace(s);
    while(!que.empty()){
      int v=que.front();que.pop();
      for(int i=0;i<(int)G[v].size();i++){
        edge &e=G[v][i];
        if(e.cap>0&&level[e.to]<0){
          level[e.to]=level[v]+1;
          que.emplace(e.to);
        }
      }
    }
  }

  T dfs(int v,int t,T f){
    if(v==t) return f;
    for(int &i=iter[v];i<(int)G[v].size();i++){
      edge &e=G[v][i];
      if(e.cap>0&&level[v]<level[e.to]){
        T d=dfs(e.to,t,min(f,e.cap));
        if(d==0) continue;
        e.cap-=d;
        G[e.to][e.rev].cap+=d;
        return d;
      }
    }
    return 0;
  }

  T flow(int s,int t,T lim){
    T fl=0;
    while(1){
      bfs(s);
      if(level[t]<0||lim==0) break;
      fill(iter.begin(),iter.end(),0);

      while(1){
        T f=dfs(s,t,lim);
        if(f==0) break;
        fl+=f;
        lim-=f;
      }
    }
    return fl;
  }

  T flow(int s,int t){
    return flow(s,t,numeric_limits<T>::max()/2);
  }

  T cut(int s,int t,int x,int a){
    static_assert(directed, "must be directed");
    auto &e=G[x][a];
    int y=e.to;
    T cr=G[y][e.rev].cap;
    if(cr==0) return e.cap=0;
    e.cap=G[y][e.rev].cap=0;
    T cap=cr-flow(x,y,cr);
    if(x!=s&&cap!=0) flow(x,s,cap);
    if(t!=y&&cap!=0) flow(t,y,cap);
    return cap;
  }

  T link(int s,int t,int x,int a,T f){
    auto &e=G[x][a];
    e.cap+=f;
    return flow(s,t,f);
  }
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed SPOJ_FASTFLOW(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  Int n,m;
  cin>>n>>m;
  Dinic<Int, false> G(n);
  for(Int i=0;i<m;i++){
    Int a,b,c;
    cin>>a>>b>>c;
    if(a==b) continue;
    a--;b--;
    G.add_edge(a,b,c);
  }
  cout<<G.flow(0,n-1)<<endl;
  return 0;
}
/*
  verified on 2019/06/10
  https://www.spoj.com/problems/FASTFLOW/
*/

signed SPOJ_BANKROB(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int n,m,s,t;
  cin>>n>>m>>s>>t;
  s--;t--;
  const int INF=5050;
  Dinic<int, true> G(n*2);
  for(int i=0;i<m;i++){
    int x,y;
    cin>>x>>y;
    x--;y--;
    G.add_edge(n+x,y,INF);
    G.add_edge(n+y,x,INF);
  }

  for(int i=0;i<n;i++)
    G.add_edge(i,n+i,1);

  cout<<G.flow(n+s,t)<<endl;
  return 0;
}
/*
  verified on 2019/06/10
  https://www.spoj.com/problems/BANKROB/
*/

signed main(){
  //SPOJ_FASTFLOW();
  //SPOJ_BANKROB();
  return 0;
}
#endif

#undef call_from_test

signed main(){
  const int DEG = 55;
  const int INF = 1<<28;
  int n,m;
  while(cin>>n>>m,n){
    Dinic<int, false> flow(n);
    int ed[DEG][55][55];
    memset(ed,0,sizeof(ed));

    for(int i=0;i<m;i++){
      int a,b;
      string s;
      cin>>a>>b>>s;
      a--;b--;
      flow.add_edge(a,b,0);
      for(string t:split(s,'+')){
        if(!count(t.begin(),t.end(),'x')){
          ed[0][a][b]+=stoi(t);
          ed[0][b][a]+=stoi(t);
        }else if(t.back()=='x'){
          t.pop_back();
          if(t.empty()) t="1";
          ed[1][a][b]+=stoi(t);
          ed[1][b][a]+=stoi(t);
        }else{
          auto v=split(t,'^');
          v[0].pop_back();
          if(v[0].empty()) v[0]="1";
          ed[stoi(v[1])][a][b]+=stoi(v[0]);
          ed[stoi(v[1])][b][a]+=stoi(v[0]);
        }
      }
    }

    vector<int> ans(DEG);
    for(int i=DEG-1;i>=0;i--){
      for(auto& v:flow.G){
        for(auto& e:v){
          if(e.cap) e.cap=INF;
          e.cap+=ed[i][e.to][flow.G[e.to][e.rev].to];
        }
      }
      ans[i]=flow.flow(0,n-1);
    }

    bool f=1;
    for(int i=DEG-1;i>=0;i--){
      if(!ans[i]){
        if(i) continue;
        if(f) cout<<ans[i],f=0;
        continue;
      }
      if(!f) cout<<"+";
      f=0;
      if(!(i&&ans[i]==1)) cout<<ans[i];
      if(i>0) cout<<"x";
      if(i>1) cout<<"^"<<i;
    }
    cout<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 3864
final_rank: 5

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
using namespace std;

typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef pair<ll, ll> LP;
typedef vector<int> vec;
typedef vector<string> svec;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;


struct poly {
	vector<int> c;
	poly(vector<int> v) {
		c = v;
	}
	poly(int x) {
		c = { x };
	}
	poly() {};
};

bool operator<(const poly &a, const poly &b) {
	if (a.c.size() != b.c.size())return a.c.size() < b.c.size();
	per(i, (int)a.c.size()) {
		if (a.c[i] != b.c[i])return a.c[i] < b.c[i];
	}
	return false;
}
poly operator-(const poly &a, const poly &b) {
	poly ret;
	int len = max(a.c.size(), b.c.size());
	ret.c.resize(len);
	rep(i, len) {
		int s = 0;
		if (i < a.c.size())s += a.c[i];
		if (i < b.c.size())s -= b.c[i];
		ret.c[i]=s;
	}
	while (ret.c.size() > 1 && ret.c.back() == 0)ret.c.pop_back();
	return ret;
}
poly operator+(const poly &a, const poly &b) {
	poly ret;
	int len = max(a.c.size(), b.c.size());
	ret.c.resize(len,0);
	rep(i, len) {
		int s = 0;
		if (i < a.c.size())s += a.c[i];
		if (i < b.c.size())s += b.c[i];
		ret.c[i]=s;
	}
	while (ret.c.size() > 1 && ret.c.back() == 0)ret.c.pop_back();
	return ret;
}
bool operator==(const poly &a, const poly &b) {
	return a.c == b.c;
}
poly min(poly a, poly b) {
	if (a < b)return a;
	return b;
}
poly in() {
	poly ret; ret.c.resize(52, 0);
	string s; cin >> s;
	int loc = 0;
	rep(i, s.length()) {
		if (s[i] == '+') {
			string t = s.substr(loc, i - loc);
			int c = 1;
			if (isdigit(t[0])) {
				int j = 0;
				while (j < t.length() && isdigit(t[j]))j++;
				c = stoi(t.substr(0, j));
			}
			bool f = false;
			int d = 1;
			rep(j, t.length()) {
				if (t[j] == 'x') {
					f = true;
				}
				if (t[j] == '^') {
					int le = j + 1;
					j++;
					while (j < t.length() && isdigit(t[j]))j++;
					d = stoi(t.substr(le, j - le));
				}
			}
			if (!f)d = 0;
			ret.c[d] = c;
			loc = i + 1;
		}
	}
	string t = s.substr(loc, t.length() - loc);
	int c = 1;
	if (isdigit(t[0])) {
		int j = 0;
		while (j < t.length() && isdigit(t[j]))j++;
		c = stoi(t.substr(0, j));
	}
	bool f = false;
	int d = 1;
	rep(j, t.length()) {
		if (t[j] == 'x') {
			f = true;
		}
		if (t[j] == '^') {
			int le = j + 1;
			j++;
			while (j < t.length() && isdigit(t[j]))j++;
			d = stoi(t.substr(le, j - le));
		}
	}
	if (!f)d = 0;
	ret.c[d] = c;
	while (ret.c.size() > 1 && ret.c.back() == 0)ret.c.pop_back();
	return ret;
}
void out(poly p) {
	if (p == 0) {
		cout << 0 << endl; return;
	}
	string ret;
	per(i, (int)p.c.size()) {
		if (p.c[i]) {
			if (i == 0 && p.c[i] == 1) {
				ret.push_back('1');
			}
			if (p.c[i] != 1) {
				string z = to_string(p.c[i]);
				ret += z;
			}
			if (i >= 1) {
				ret.push_back('x');
				if (i > 1) {
					ret.push_back('^');
					string z = to_string(i);
					ret += z;
				}
			}
			ret.push_back('+');
		}
	}
	ret.pop_back();
	cout << ret << endl;
}


struct edge { int to; poly cap; int rev; };


vector<edge> G[100000];
bool used[100000];
void add_edge(int from, int to, poly cap) {
	G[from].push_back(edge{ to, cap, (int)G[to].size() });
	G[to].push_back(edge{ from, 0, (int)G[from].size() - 1 });
}
poly dfs(int v, int t, poly f) {
	if (v == t)return f;
	used[v] = true;
	for (int i = 0; i < (int)G[v].size(); i++) {
		edge &e = G[v][i];
		if (!used[e.to] && 0<e.cap) {
			poly d = dfs(e.to, t, min(f, e.cap));
			if (0<d) {
				e.cap = e.cap-d;
				G[e.to][e.rev].cap = G[e.to][e.rev].cap+d;
				return d;
			}
		}
	}
	return 0;
}
const poly inf(vector<int>(52, 1));
poly max_flow(int s, int t,int sz) {
	poly flow = 0;
	for (;;) {
		fill(used, used + sz, false);
		poly f = dfs(s, t, inf);
		//out(f);
		if (f == poly(0))return flow;
		flow = flow+f;
		//out(flow);
	}
}
bool isdigit(char t) {
	return '0' <= t && t <= '9';
}
int n, m;
void solve() {
	rep(i, n)G[i].clear();
	rep(i, m) {
		int a, b; cin >> a >> b; a--; b--;
		poly p = in();
		add_edge(a, b, p);
		add_edge(b, a, p);
	}
	poly ans = max_flow(0, n - 1,n);
	//cout << "ans is ";
	out(ans);
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	//cout << fixed << setprecision(10);
	//init();
	while(cin>>n>>m,n)solve();
	//stop
		return 0;
}
accuracy: 1
time_ms: 6620
memory_kb: 6012
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

struct Polynomial{
  using P = Polynomial;
  vector<Int> co;
  Polynomial():co(1,1){}
  Polynomial(Int s):co(s,0){}
  Polynomial(vector<Int> co):co(co){}
  
  size_t size() const{
    return co.size();
  };

  void shrink(){
    while(co.size()>1u&&!co.back())
      co.pop_back();
  }

  void reduce(){
    Int g=abs(co.back());
    if(!g) return;
    for(Int c:co)
      if(c!=0) g=__gcd(g,abs(c));
    if(co.back()<0) g*=-1;
    for(Int &c:co) c/=g;
  }

  void print(){
    shrink();
    // reduce();    
    Int n=size(),flg=0;    
    if(n==1){      
      cout<<co[0]<<endl;
      return;
    }
    for(Int i=n-1;i>0;i--){
      if(!co[i]) continue;
      flg=1;
      if(i!=n-1&&co[i]>0) cout<<"+";
      if(co[i]==-1) cout<<"-";
      else if(co[i]!=1) cout<<co[i];
      
      cout<<"x";
      if(i!=1) cout<<"^"<<i;
    }
    if(co[0]){
      if(flg&&co[0]>0) cout<<"+";
      cout<<co[0];
    }
    cout<<endl;
  }

  Int operator[](Int i) const{
    return co[i];
  }

  Int &operator[](Int i){
    return co[i];
  }

  P operator-() const{
    P res=*this;
    for(Int &c:res.co) c*=-1;
    return res;
  }

  P operator+(const P &a) const{
    Int n=size(),m=a.size();
    P res(max(n,m));
    for(Int i=0;i<n;i++) res[i]+=co[i];
    for(Int i=0;i<m;i++) res[i]+=a[i];
    return res;
  }
  P operator-(const P &a) const{return *this+(-a);};

  P operator*(const P &a) const{
    Int n=size(),m=a.size();
    P res(n+m);
    for(Int i=0;i<n;i++)
      for(Int j=0;j<m;j++)
        res[i+j]+=co[i]*a[j];
    res.shrink();
    return res;
  }

  P pow(Int k) const{
    P a(*this);
    P res;
    for(Int i=0;i<k;i++) res=res*a;
    return res;
  }
  
  pair<P, P> divide(const P &a) const{
    Int n=size(),m=a.size(),s=n-m+1;
    if(s<0) return make_pair(P(1),*this);
    P div(s);
    P rest=*this;
    for(Int i=0;i<s;i++){
      if(rest[n-(i+1)]%a[m-1]!=0)
        for(Int &c:rest.co) c*=a[m-1];
      Int d=rest[n-(i+1)]/a[m-1];
      div[s-(i+1)]=d;
      for(Int j=m;j>0;j--) rest[n-(i+j)]-=a[m-j]*d;
    }
    return make_pair(div,rest);
  }
  
  P operator/(const P &a) const{return divide(a).first;};
  P operator%(const P &a) const{return divide(a).second;};  
};

Polynomial gcd(Polynomial a,Polynomial b){
  a.shrink();a.reduce();
  b.shrink();b.reduce();
  if(a.size()<b.size()) swap(a,b);
  if(b.size()==1u&&!b[0]) return a;
  return gcd(b,a%b);
}

Polynomial expr(string s,Int &p);
Polynomial factor(string s,Int &p);
Polynomial term(string s,Int &p);
Int number(string s,Int &p);

Polynomial expr(string s,Int &p){
  //cout<<"expr"<<endl;
  Polynomial res;
  if(s[p]=='-'){
    p++;
    res=-factor(s,p);
  }else res=factor(s,p);
  
  while(p<(Int)s.size()){
    //res.print();
    if(s[p]=='+'){
      p++;
      res=res+factor(s,p);
      continue;
    }
    if(s[p]=='-'){
      p++;
      res=res-factor(s,p);
      continue;
    }
    break;
  }
  //res.print();
  return res;
}
Polynomial factor(string s,Int &p){
  //cout<<"factor"<<endl;
  Polynomial res=term(s,p);
  while(p<(Int)s.size()){
    //res.print();
    if(s[p]=='+') break;
    if(s[p]=='-') break;
    if(s[p]==')') break;
    res=res*term(s,p);
  }
  return res;
}
Polynomial term(string s,Int &p){
  //cout<<"term"<<endl;
  if(s[p]=='('){
    p++;
    Polynomial res=expr(s,p);
    assert(s[p]==')');
    p++;
    if(s[p]=='^'){
      p++;
      Int k=number(s,p);
      res=res.pow(k);
    }
    //res.print();
    return res;
  }
  Int v=(s[p]=='x'?1:number(s,p));
  if(p<(Int)s.size()&&s[p]=='x'){      
    p++;
    if(p<(Int)s.size()&&s[p]=='^'){
      p++;
      Int k=number(s,p);
      Polynomial res(k+1);
      res[k]=v;
      //res.print();
      return res;
    }
    Polynomial res(2);
    res[1]=v;
    //res.print();
    return res;
  }
  Polynomial res(1);
  res[0]=v;
  return res;
}

Int number(string s,Int &p){
  Int res=0;
  while(p<(Int)s.size()&&isdigit(s[p]))
    res=res*10+(s[p++]-'0');
  return res;
}

Polynomial calc(string s){
  Int p=0;
  return expr(s,p);
}


template<typename T,bool directed>
struct Dinic{
  struct edge {
    Int to;
    T cap;
    Int rev;
    edge(){}
    edge(Int to,T cap,Int rev):to(to),cap(cap),rev(rev){}
  };

  T INF;
  vector<vector<edge> > G;
  vector<Int> level,iter;

  Dinic(){}  
  Dinic(Int n,T INF):INF(INF),G(n),level(n),iter(n){}
  
  void add_edge(Int from,Int to,Int cap){
    G[from].emplace_back(to,cap,G[to].size());
    G[to].emplace_back(from,directed?0:cap,G[from].size()-1);
  }
  
  void bfs(Int s){
    fill(level.begin(),level.end(),-1);
    queue<Int> que;
    level[s]=0;
    que.emplace(s);
    while(!que.empty()){
      Int v=que.front();que.pop();
      for(Int i=0;i<(Int)G[v].size();i++){
        edge &e=G[v][i];
        if(e.cap>0&&level[e.to]<0){
          level[e.to]=level[v]+1;
          que.emplace(e.to);
        }
      }
    }
  }
  
  T dfs(Int v,Int t,T f){
    if(v==t) return f;
    for(Int &i=iter[v];i<(Int)G[v].size();i++){
      edge &e=G[v][i];
      if(e.cap>0&&level[v]<level[e.to]){
        T d=dfs(e.to,t,min(f,e.cap));
        if(d==0) continue;
        e.cap-=d;
        G[e.to][e.rev].cap+=d;
        return d;      
      }
    }
    return 0;
  }
  
  T flow(Int s,Int t,T lim){
    T fl=0;
    while(1){
      bfs(s);
      if(level[t]<0||lim==0) break;
      fill(iter.begin(),iter.end(),0);
      
      while(1){
        T f=dfs(s,t,lim);
        if(f==0) break;
        fl+=f;
        lim-=f;
      }
    }
    return fl;
  }

  T flow(Int s,Int t){
    return flow(s,t,INF);
  }
};

//INSERT ABOVE HERE
signed main(){
  Int n,m;
  while(cin>>n>>m,n){
    using P = pair<Int, Polynomial>;
    vector<vector<P> > G(n);
    for(Int i=0;i<m;i++){
      Int x,y;
      string s;
      cin>>x>>y>>s;
      auto p=calc(s);
      x--;y--;
      G[x].emplace_back(y,p);
      G[y].emplace_back(x,p);
    }
    const Int INF = 1e5;
    Dinic<Int, true> F(n,INF);
    Polynomial ans(1);
    
    for(Int d=50;d>=0;d--){   
      for(Int v=0;v<n;v++){
        for(auto e:G[v]){
          Int u=e.first;
          auto &p=e.second;
          if(d<(Int)p.size()&&p[d]){
            F.add_edge(v,u,p[d]);
          }          
        }
      }
      Polynomial res(d+1);
      res[d]=F.flow(0,n-1);
      ans=ans+res;
      
      for(auto &v:F.G)
        for(auto &e:v)
          if(e.cap>0) e.cap=INF;
    }
    ans.print();
  } 
  return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 6736
final_rank: 14

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pi;
typedef pair<double,double> pd;
typedef pair<double,ll> pdl;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;


template<typename T,bool directed>
struct Dinic{
    struct edge {
        int to;
        T cap;
        int rev;
        edge(){}
        edge(int to,T cap,int rev):to(to),cap(cap),rev(rev){}
    };
    
    T INF;
    vector<vector<edge> > G;
    vector<int> level,iter;
    
    Dinic(){}
    Dinic(int n,T INF):INF(INF),G(n),level(n),iter(n){}
    
    pll add_edge(int from,int to,int cap){
        G[from].emplace_back(to,cap,G[to].size());
        G[to].emplace_back(from,directed?0:cap,G[from].size()-1);
        return {G[from].size()-1,G[to].size()-1};
    }
    
    void bfs(int s){
        fill(level.begin(),level.end(),-1);
        queue<int> que;
        level[s]=0;
        que.emplace(s);
        while(!que.empty()){
            int v=que.front();que.pop();
            for(int i=0;i<(int)G[v].size();i++){
                edge &e=G[v][i];
                if(e.cap>0&&level[e.to]<0){
                    level[e.to]=level[v]+1;
                    que.emplace(e.to);
                }
            }
        }
    }
    
    T dfs(int v,int t,T f){
        if(v==t) return f;
        for(int &i=iter[v];i<(int)G[v].size();i++){
            edge &e=G[v][i];
            if(e.cap>0&&level[v]<level[e.to]){
                T d=dfs(e.to,t,min(f,e.cap));
                if(d==0) continue;
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
        return 0;
    }
    
    T flow(int s,int t,T lim){
        T fl=0;
        while(1){
            bfs(s);
            if(level[t]<0||lim==0) break;
            fill(iter.begin(),iter.end(),0);
            
            while(1){
                T f=dfs(s,t,lim);
                if(f==0) break;
                fl+=f;
                lim-=f;
            }
        }
        return fl;
    }
    
    T flow(int s,int t){
        return flow(s,t,INF);
    }
};

const ll MX=1LL<<30;

bool number(char c){return '0'<=c && c<='9';}

void toNum(string &s,vector<ll> &ret){
    ll k=0;
    for(int t=0;t<s.size();t++){
        if(s[t]=='x'){
            ll z=0;
            while(t<s.size() && s[t]!='+'){
                if(number(s[t])){z*=10; s[t]-='0'; z+=s[t];}
                ++t;
            }
            ret[max(z,1LL)]=max(k,1LL);
            k=0;
            continue;
        }
        else{
            k*=10;
            s[t]-='0';
            k+=s[t];
        }
    }
    ret[0]=k;
}

void toStr(vector<ll> &ans){
    while(ans.size()>0 && ans.back()==0){ans.pop_back();}
    ll last=0;
    while(last<ans.size() && ans[last]==0){last++;}
    if(last==ans.size()){cout<<0<<endl; return;}
    for(ll i=ans.size()-1;i>=last;i--){
        if(ans[i]==0){continue;}
        if(ans[i]!=1 || i==0){cout<<ans[i];}
        if(i>0){cout<<"x";}
        if(i>1){cout<<"^"<<i;}
        if(i!=last){cout<<"+";}
    }
    cout<<endl;
}

int main(){
    ll n,m;
    while(cin>>n>>m){
        if(n==0){break;}
    vector<pll> Edge(m);
    vector<vector<ll>> Cost(m,vector<ll>(51,0));
    vector<pll> num(m);
    for(int i=0;i<m;i++){
        cin>>Edge[i].F>>Edge[i].S;
        Edge[i].F--; Edge[i].S--;
        if(Edge[i].F>Edge[i].S){swap(Edge[i].F,Edge[i].S);}
        string s;
        cin>>s;
        toNum(s,Cost[i]);
    }
    vector<ll> ans(51,0);
    Dinic<ll,false> Flow(n,MX);
    for(int i=0;i<m;i++){
        num[i]=Flow.add_edge(Edge[i].F,Edge[i].S,0);
    }
    for(ll time=50;time>=0;time--){
        for(int i=0;i<m;i++){
            if(Flow.G[Edge[i].F][num[i].F].cap>0){Flow.G[Edge[i].F][num[i].F].cap=MX;}
            if(Flow.G[Edge[i].S][num[i].S].cap>0){Flow.G[Edge[i].S][num[i].S].cap=MX;}
        }
        for(int i=0;i<m;i++){
            Flow.G[Edge[i].F][num[i].F].cap+=Cost[i][time];
            Flow.G[Edge[i].S][num[i].S].cap+=Cost[i][time];
        }
        ans[time]=Flow.flow(0,n-1);
    }
    toStr(ans);
    }
    
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3280
final_rank: 1

code_snippet: #include <cstdio>
#include <cstdint>
#include <cassert>
#include <cctype>
#include <vector>
#include <map>
#include <algorithm>
#include <string>
#include <stdexcept>
#include <iostream>
#include <functional>
#include <queue>

class polynomial;
static const std::vector<std::string> ops={"+-", "*/%", "^"};
// operator % を定義していると多項式の GCD とかも簡単に書けるんですよね
// べき乗の演算子はふつう右結合のはずなんですが，そういう入力はこないと
// 思うので，左結合で書いてしまいます．

polynomial parse(const std::string&, size_t&, size_t);

std::string normalize(const std::string& s) {
  std::string res;
  enum { NONE, PAREN, FACTOR, OPERATOR } last = NONE;
  for (size_t i=0; i<s.length(); ++i) {
    if (s[i] == '(') {
      if (last == FACTOR) res += '*';
      res += '(';
      last = PAREN;
    } else if (s[i] == ')') {
      res += ')';
      last = FACTOR;
    } else if (isalnum(s[i])) {
      if (last == FACTOR) res += '*';
      res += s[i];
      if (isdigit(s[i])) {
        while (isdigit(s[i+1]))
          res += s[++i];
      }
      last = FACTOR;
    } else if (!isspace(s[i])) {
      res += s[i];
      last = OPERATOR;
    }
  }
  return res;
}

class polynomial {
  using deg_type = int;
  using coef_type = intmax_t;
  // e.g., polynomial("2x^2+1") => cs: {"xx": 2, "": 1}
  // 冷静に考えると，polynomial("x^100000") でつらくなりますね
  // {("x", 2): 2, ("", 0): 1} みたいにするべき？
  // そうした方がいい気がするのでそのうちします
  // と思ったけど ab みたいなのをどう扱いますか？ やめます．
  // やっぱりやめません．
  // というか文字を決めうちでいいなら上の式も {2: 2, 0: 1} でいいですね
  std::map<deg_type, coef_type> cs;

  polynomial& normalized() {
    for (auto it=cs.begin(); it!=cs.end();) {
      if (it->second == 0) {
        it = cs.erase(it);
      } else {
        ++it;
      }
    }
    return *this;
  }

public:
  /* constructors */
  polynomial(const std::string& s) {
    std::string t = normalize(s);
    size_t i = 0;
    polynomial tmp = parse(t, i, 0);
    cs = std::move(tmp.cs);
  }

  polynomial(deg_type d, coef_type c) {
    cs[d] = c;
  }

  polynomial(coef_type c) {
    cs[0] = c;
  }

  polynomial() {}

  /* binary operations (@=) */
  polynomial& operator +=(const polynomial& rhs) {
    for (const auto& p: rhs.cs) cs[p.first] += p.second;

    // Poly("+x") + Poly("-x") の結果 Poly("0") になりますが，このとき
    // cs は {"": 0} になるべきで {"x": 0} になるべきではありません
    return normalized();
  }

  polynomial& operator -=(const polynomial& rhs) {
    for (const auto& p: rhs.cs) cs[p.first] -= p.second;
    return normalized();
  }

  polynomial& operator *=(const polynomial& rhs) {
    // Note: this と *rhs が identical でもつらくならない必要がある
    std::map<deg_type, coef_type> tmp;
    for (const auto& p1: cs)
      for (const auto& p2: rhs.cs) {
        deg_type param = p1.first+p2.first;
        tmp[param] += p1.second * p2.second;
      }
    cs = std::move(tmp);
    return normalized();
  }

  // not implemented
  polynomial& operator /=(const polynomial& rhs);  
  polynomial& operator %=(const polynomial& rhs);  

  polynomial& operator ^=(const polynomial& rhs) {
    if (!(rhs.cs.size() == 1 && rhs.cs.begin()->first == 0))
      throw std::logic_error("y should be constant in x^y");

    int iexp = rhs.cs.at(0);
    if (iexp < 0)
      throw std::logic_error("y should be non-negative in x^y");

    polynomial dbl(*this);
    cs.clear();
    cs[0] = 1;
    for (; iexp; iexp>>=1) {
      if (iexp & 1) (*this) *= dbl;
      dbl *= dbl;
    }
    return normalized();
  }

  // wrapper
  polynomial& op_eq(char op, const polynomial& rhs) {
    switch (op) {
    case '+': return (*this) += rhs;
    case '-': return (*this) -= rhs;
    case '*': return (*this) *= rhs;
    // case '/': return (*this) /= rhs;
    // case '%': return (*this) %= rhs;
    case '^': return (*this) ^= rhs;
    default: assert(false);
    }
  }

  /* binary opeartions (@) */
  polynomial operator +(const polynomial& other) const { return polynomial(*this) += other; }
  polynomial operator -(const polynomial& other) const { return polynomial(*this) -= other; }
  polynomial operator *(const polynomial& other) const { return polynomial(*this) *= other; }
  // polynomial operator %(const polynomial& other) const { return polynomial(*this) %= other; }
  // polynomial operator /(const polynomial& other) const { return polynomial(*this) /= other; }
  polynomial operator ^(const polynomial& other) const { return polynomial(*this) ^= other; }

  /* binary opeartions (relations) */
  bool operator <(const polynomial& rhs) const {
    polynomial tmp(*this);
    tmp -= rhs;
    // lhs-rhs < 0 <=> lhs < rhs
    // で，最高次的なやつのの符号で決めます
    if (tmp.cs.empty()) return false;
    return std::prev(tmp.cs.end())->second < 0;
  }

  bool operator ==(const polynomial& rhs) const {
    return cs == rhs.cs;
  }

  operator std::string() const {
    std::string res;
    for (auto it=cs.rbegin(); it!=cs.rend(); ++it) {
      deg_type d = it->first;
      coef_type c = it->second;
      if (c == 0) continue;
      if (c > 0) {
        if (!res.empty()) res += '+';
      } else {
        res += '-';
        c = -c;
      }
      if (c > 1 || d == 0) res += std::to_string(c);
      if (d > 0) {
        res += 'x';
        if (d > 1) {
          res += '^';
          res += std::to_string(d);
        }
      }
    }
    if (res.empty()) res = "0";
    return res;
  }
};

polynomial parse(const std::string& s, size_t& i, size_t preced) {
  if (preced == ops.size()) {
    if (s[i] == '(') {
      polynomial res = parse(s, ++i, 0);
      assert(s[i] == ')');
      ++i;
      return res;
    }
    if (isalpha(s[i])) {
      assert(s[i] == 'x');
      ++i;
      return polynomial(1, 1);
    }
    if (isdigit(s[i])) {
      intmax_t res = s[i]-'0';
      while (++i < s.length() && isdigit(s[i]))
        res = res*10+s[i]-'0';
      return polynomial(0, res);
    }
    assert(false);
  }

  polynomial res = parse(s, i, preced+1);
  while (i < s.length()) {
    char op = s[i];
    if (!std::count(ops[preced].begin(), ops[preced].end(), op)) break;
    polynomial tmp = parse(s, ++i, preced+1);
    res.op_eq(op, tmp);
  }
  return res;
}

template <class Tp>
Tp inf() { return Tp(); }
template <>
polynomial inf() { return polynomial(100, 1); }

template <class Tp>
struct Edge {
  size_t src, dst;
  Tp cap;
  size_t rev;
  Edge(size_t src, size_t dst, Tp cap, size_t rev):
    src(src), dst(dst), cap(cap), rev(rev)
  {}
};

template <class Tp>
struct graph: public std::vector<std::vector<Edge<Tp>>> {
  graph(size_t n): std::vector<std::vector<Edge<Tp>>>(n) {}

  void connect_with(size_t src, size_t dst, Tp cap) {
    (*this)[src].emplace_back(src, dst, cap, (*this)[dst].size());
    (*this)[dst].emplace_back(dst, src, cap, (*this)[src].size()-1);
  }
};

template <class Tp>
std::vector<int> distance(graph<Tp>& g, size_t s) {
  std::vector<int> cost(g.size(), -1);
  std::queue<size_t> q;
  cost[s] = 0;
  q.emplace(s);
  while (!q.empty()) {
    size_t v = q.front();
    q.pop();
    for (const auto& e: g[v]) {
      if (Tp(0) < e.cap && cost[e.dst] < 0) {
        cost[e.dst] = cost[v] + 1;
        q.push(e.dst);
      }
    }
  }
  return cost;
}

template <class Tp>
Tp max_flow(graph<Tp>& g, size_t s, size_t t) {
  Tp flow = Tp(0);
  std::vector<size_t> iter;
  std::vector<int> cost;

  std::function<Tp (size_t, Tp)> augment=[&](size_t v, Tp f)->Tp {
    if (v == t) return f;
    for (size_t& i=iter[v]; i<g[v].size(); ++i) {
      Edge<Tp>& e = g[v][i];
      if (Tp(0) < e.cap && cost[v] < cost[e.dst]) {
        Tp d = augment(e.dst, std::min(f, e.cap));
        if (Tp(0) < d) {
          e.cap -= d;
          g[e.dst][e.rev].cap += d;
          return d;
        }
      }
    }
    return Tp(0);
  };

  while (true) {
    cost = distance(g, s);
    if (cost[t] < 0) return flow;
    iter.assign(g.size(), 0);
    Tp f;
    while (Tp(0) < (f = augment(s, inf<Tp>())))
      flow += f;
  }
}

int testcase_ends() {
  size_t N, M;
  scanf("%zu %zu", &N, &M);

  if (N == 0 && M == 0) return 1;

  graph<polynomial> g(N);
  for (size_t i=0; i<M; ++i) {
    size_t src, dst;
    scanf("%zu %zu", &src, &dst);
    --src;
    --dst;

    char buf[1024];
    scanf("%s", buf);
    std::string s = buf;

    polynomial p(s);
    g.connect_with(src, dst, p);
  }

  printf("%s\n", std::string(max_flow(g, 0, N-1)).c_str());
  return 0;
}

int main() {
  while (!testcase_ends()) {}
}
accuracy: 1
time_ms: 620
memory_kb: 6332
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

int number(string s) {
    int ret = 0, pos = 0;
    while (pos < (int)s.size() && isdigit(s[pos])) {
        ret = ret * 10 + (s[pos] - '0');
        pos++;
    }
    return ret;
}

class Capacity {
public:
    int coef[102] = {};
    int dim = 0;

    Capacity(){};
    Capacity(string s) {
        int prev_pos = 0;
        int x_pos = -1, pow_pos = -1;
        for (int i = 0; i <= (int)s.size(); i++) {
            if (i == (int)s.size() || s[i] == '+') {
                auto term = s.substr(prev_pos, i-prev_pos);

                int c = 1;
                if (x_pos != prev_pos) c = number(term);

                int d = 0;
                if (pow_pos != -1) d = number(term.substr(pow_pos-prev_pos+1));
                else if (x_pos != -1) d = 1;

                coef[d] = c;
                dim = max(dim, d);

                x_pos = -1, pow_pos = -1;
                prev_pos = i + 1;
            } else if (s[i] == 'x') {
                x_pos = i;
            } else if (s[i] == '^') {
                pow_pos = i;
            }
        }
    }
    bool is_zero(){
        return (dim == 0 && coef[0] == 0);
    }

    void output() {
        string ret = "";
        for (int i = dim; i >= 0; i--) {
            if (coef[i] == 0 && ret.size() > 0)
                continue;

            if (ret.size() && coef[i] >= 0) ret += "+";
            if (coef[i] > 1 || (i == 0 && coef[i] == 1) || (i == 0 && ret.size() == 0))
                ret += to_string(coef[i]);
            if (i != 0) ret += "x";
            if (i > 1){
                ret += "^";
                ret += to_string(i);
            }
        }
        cout << ret << endl;
    }
};
Capacity operator+(const Capacity &lv, const Capacity &rv) {
    Capacity ret;
    int dim = max(lv.dim, rv.dim);
    for (int i = 0; i <= dim; i++) {
        ret.coef[i] = lv.coef[i] + rv.coef[i];
    }
    ret.dim = dim;
    return ret;
}
Capacity operator-(const Capacity &lv, const Capacity &rv) {
    Capacity ret;

    int dim = max(lv.dim, rv.dim);
    bool erase = true;
    for (int i = dim; i >= 0; i--) {
        ret.coef[i] = lv.coef[i] - rv.coef[i];

        if (erase && ret.coef[i] == 0) dim--;
        else erase = false;
    }
    if (dim < 0) dim = 0;
    ret.dim = dim;
    return ret;
}
bool operator>(const Capacity &lv, const Capacity &rv) {
    if (lv.dim != rv.dim) return lv.dim > rv.dim;
    for (int i = lv.dim; i >= 0; i--) {
        if (lv.coef[i] == rv.coef[i])
            continue;
        return lv.coef[i] > rv.coef[i];
    }
    return false;
}
Capacity min(Capacity &a, Capacity &b) {
    if (a > b) return b;
    return a;
}

struct edge {
    int to;
    Capacity cap;
    int rev;
};

int N, M;
vector<vector<edge>> G;
bool used[51];
Capacity max_cap("101x^101");

void add_edge(int from, int to, const Capacity &cap) {
    G[from].push_back({to, cap, (int)G[to].size()});
    G[to].push_back({from, Capacity(), (int)G[from].size() - 1});
}

Capacity dfs(int v, int t, Capacity f) {
    if (v == N-1) return f;
    used[v] = true;
    for (int i = 0; i < (int)G[v].size(); i++) {
        edge &e = G[v][i];
        if (!used[e.to] && !e.cap.is_zero()) {
            Capacity d = dfs(e.to, t, min(f, e.cap));
            if (!d.is_zero()) {
                e.cap = e.cap - d;
                G[e.to][e.rev].cap = G[e.to][e.rev].cap + d;
                return d;
            }
        }
    }
    return Capacity();
}

int main() {
    while (cin >> N >> M, N + M) {
        G = vector<vector<edge>>(N);
        for (int i = 0; i < M; i++) {
            int from, to; string exp;
            cin >> from >> to >> exp;
            from--, to--;
            add_edge(from, to, Capacity(exp));
            add_edge(to, from, Capacity(exp));
        }

        Capacity flow;
        while (true)
        {
            memset(used, false, sizeof(used));
            Capacity f = dfs(0, N-1, max_cap);
            if (f.is_zero()) break;
            flow = flow + f;
        }
        flow.output();
    }
}
accuracy: 1
time_ms: 3400
memory_kb: 4412
final_rank: 8

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 110
#define MAX_DEGREE 50

//辺を表す構造体(行先、容量、逆辺のインデックス)
struct Edge{
	Edge(int arg_to,vector<int> arg_capacity,int arg_rev_index){
		to = arg_to;
		capacity = arg_capacity;
		rev_index = arg_rev_index;
	}
	int to,rev_index;
	vector<int> capacity;
};

int V,E;
int max_degree;

vector<Edge> G[NUM]; //グラフの隣接リスト表現
int dist[NUM]; //sourceからの距離
int cheked_index[NUM]; //どこまで調べ終わったか

//fromからtoへ向かう容量capacityの辺をグラフに追加する
void add_edge(int from,int to,vector<int> capacity){

	vector<int> ZERO;
	for(int i = 0; i <= MAX_DEGREE; i++)ZERO.push_back(0);

	G[from].push_back(Edge(to,capacity,G[to].size()));
	G[to].push_back(Edge(from,ZERO,G[from].size()-1)); //逆辺の、初期容量は0
}

vector<int> get_smaller(vector<int> A,vector<int> B){

	for(int i = max_degree; i >= 0; i--){
		if(A[i] != B[i]){
			if(A[i] > B[i]){ //最高次数が小さい方を採用
				return B;
			}else{
				return A;
			}
		}
	}
	return A;
}


bool is_zero(vector<int> add){
	for(int i = 0; i <= max_degree; i++){
		if(add[i] != 0){
			return false;
		}
	}
	return true;
}

//sourceからの最短距離をBFSで計算する
void bfs(int source){
	for(int i = 0; i < V; i++)dist[i] = -1;
	queue<int> Q;
	dist[source] = 0;
	Q.push(source);

	while(!Q.empty()){
		int node_id = Q.front();
		Q.pop();
		for(int i = 0; i < G[node_id].size(); i++){
			Edge &e = G[node_id][i];
			if(is_zero(e.capacity) == false && dist[e.to] < 0){ //辺の容量が正で、かつエッジの行先に未訪問の場合
				dist[e.to] = dist[node_id]+1;
				Q.push(e.to);
			}
		}
	}
}

//増加パスをDFSで探す
vector<int> dfs(int node_id,int sink,vector<int> tmp_min){

	if(node_id == sink)return tmp_min; //終点についたらtmp_min[★最小の容量★]をreturn

	vector<int> ret;

	for(int &i = cheked_index[node_id]; i < G[node_id].size(); i++){ //node_idから出ているエッジを調査

		Edge &e = G[node_id][i];

		if(is_zero(e.capacity) == false && dist[node_id] < dist[e.to]){ //流せる余裕があり、かつsourceからの距離が増加する方法である場合

			ret = dfs(e.to,sink,get_smaller(tmp_min,e.capacity)); //流せるだけ流す

			if(!is_zero(ret)){ //流せた場合
				for(int k = 0; k <= max_degree; k++){
					e.capacity[k] -= ret[k]; //流した分、エッジの容量を削減する
					G[e.to][e.rev_index].capacity[k] += ret[k]; //逆辺の容量を、流した分だけ増加させる
				}
				return ret;
			}
		}
	}
	//★★エッジのused状況により、for文の内部に到達しない場合あり★★
	if(ret.size() == 0){
		for(int i = 0; i <= max_degree; i++)ret.push_back(0);
	}

	return ret;
}

//sourceからsinkへの最大流を求める
vector<int> max_flow(int source,int sink){ //source:始点 sink:終点

	vector<int> ret,add,tmp_min;
	for(int i = 0; i <= max_degree; i++)ret.push_back(0);

	while(true){ //増加パスが存在する限り、流量を追加し続ける
		bfs(source);
		if(dist[sink] < 0)break; //sourceからsinkへと辿り着く残余グラフがない、つまり増加パスが無くなった場合、break
		for(int i = 0; i < V; i++)cheked_index[i] = 0;

		tmp_min.clear();
		for(int i = 0; i <= max_degree; i++)tmp_min.push_back(BIG_NUM);

		while(!is_zero(add = dfs(source,sink,tmp_min))){ //増加パスが見つかる間、加算
			for(int i = 0; i <= max_degree; i++){
				ret[i] += add[i];
			}
		}
	}

	return ret;
}

bool is_number(char ch){
	return ch >= '0' && ch <= '9';
}

void func(){

	for(int i = 0; i < NUM; i++)G[i].clear();

	int from,to,index,tmp,tmp_degree;
	char buf[1000];
	vector<int> input;

	max_degree = 0;

	for(int loop = 0; loop < E; loop++){

		input.clear();
		for(int i = 0; i <= MAX_DEGREE; i++)input.push_back(0);

		scanf("%d %d %s",&from,&to,buf);
		from--;
		to--;

		index = 0;

		while(buf[index] != '\0'){

			if(is_number(buf[index])){ //係数の場合

				tmp = 0;
				while(is_number(buf[index])){
					tmp = 10*tmp+buf[index]-'0';
					index++;
				}
				if(buf[index] == 'x'){

					index++;

				}else{ //★定数の場合:最後の項であるはず★

					input[0] = tmp;
					break;
				}

			}else if(buf[index] == 'x'){
				tmp = 1;
				index++;
			}

			if(buf[index] == '^'){ //ここに来るまでに係数が設定されているはず

				tmp_degree = 0;
				index++;
				while(is_number(buf[index])){
					tmp_degree = 10*tmp_degree+buf[index]-'0';
					index++;
				}

			}else{ //xの一次項
				tmp_degree = 1;
			}
			input[tmp_degree] = tmp;
			max_degree = max(max_degree,tmp_degree);
			if(buf[index] == '+')index++;
		}

		add_edge(from,to,input);
		add_edge(to,from,input);
	}

	vector<int> ans = max_flow(0,V-1);

	bool is_First = true;

	for(int i = max_degree; i >= 0; i--){
		if(ans[i] == 0)continue;

		if(is_First){
			is_First = false;
		}else{
			printf("+");
		}
		if(ans[i] > 1 || i == 0){
			printf("%d",ans[i]);
		}
		if(i > 0){
			printf("x");
			if(i > 1){
				printf("^%d",i);
			}
		}
	}
	if(is_First){
		printf("0");
	}

	printf("\n");
}

int main(){

	while(true){
		scanf("%d %d",&V,&E);
		if(V == 0 && E == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3452
final_rank: 3

code_snippet: #include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <vector>

using namespace std;

string toStr(long long n)
{
	char buf[50];
	sprintf(buf, "%d", n);
	return buf;
}

struct poly{
	long long a[55];
	poly(){
		for(long long i = 0; i <= 51; i++) a[i] = 0;
	}
	poly(string s)
	{
		for(long long i = 0; i <= 51; i++) a[i] = 0;
		
		s = s + "+";
		string buf;
		long long state = 0, coe;
		for(long long i = 0; i < s.size(); i++){
			if(state == 0){
				if(s[i] == 'x'){
					if(buf == "") buf = "1";
					coe = atoi(buf.c_str());
					buf = "";
					state = 1;
				}
				else if(s[i] == '+'){
					a[0] = atoi(buf.c_str());
					buf = "";
				}
				else{
					buf += s[i];
				}
			}
			else if(state == 1){
				if(s[i] == '^'){
					state = 2;
				}
				else if(s[i] == '+'){
					a[1] = coe;
					state = 0;
				}
			}
			else if(state == 2){
				if(s[i] == '+'){
					a[atoi(buf.c_str())] = coe;
					buf = "";
					state = 0;
				}
				else{
					buf += s[i];
				}
			}
		}
	}
	string output()
	{
		string ret;
		for(long long i = 51; i > 0; i--){
			if(a[i] == 0) continue;
			if(a[i] != 1) ret += toStr(a[i]);
			ret += "x";
			if(i > 1) ret += "^" + toStr(i);
			ret += "+";
		}
		if(ret.size() > 0){
			if(a[0] == 0) ret.erase(ret.end()-1);
			else ret += toStr(a[0]);
		}
		else ret = toStr(a[0]);
		return ret;
	}
	poly operator+(const poly& obj)
	{
		poly ret;
		for(long long i = 0; i <= 51; i++){
			ret.a[i] = a[i] + obj.a[i];
		}
		return ret;
	}
	poly operator-(const poly& obj)
	{
		poly ret;
		for(long long i = 0; i <= 51; i++){
			ret.a[i] = a[i] - obj.a[i];
		}
		return ret;
	}
	bool operator<(const poly& obj)const
	{
		for(long long i = 51; i >= 0; i--){
			if(a[i] < obj.a[i]) return true;
			if(a[i] > obj.a[i]) return false;
		}
		return false;
	}
	bool operator<=(const poly& obj)const
	{
		for(long long i = 51; i >= 0; i--){
			if(a[i] < obj.a[i]) return true;
			if(a[i] > obj.a[i]) return false;
		}
		return true;
	}
};


struct edge{
	long long to, rev;
	poly cap;
	edge(long long a, string b, long long c){
		to = a, cap = b, rev = c;
	}
};

long long N, M;
vector<edge> G[205];
long long S, T;
bool used[205];
const poly zero, inf("x^51");

poly dfs(long long v, poly f)
{
	used[v] = true;
	if(v == T) return f;
	
	poly ret;
	for(long long i = 0; i < G[v].size(); i++){
		if(used[G[v][i].to] || G[v][i].cap <= zero) continue;
		ret = dfs(G[v][i].to, min(f, G[v][i].cap));
		if(zero < ret){
			G[v][i].cap = G[v][i].cap - ret;
			G[G[v][i].to][G[v][i].rev].cap = G[G[v][i].to][G[v][i].rev].cap + ret;
			return ret;
		}
	}
	return zero;
}

int main(void)
{
	while(1){
		cin >> N >> M;
		if(N == 0 && M == 0) break;
		
		for(long long i = 1; i <= N; i++) G[i].clear();
		
		long long u, v; string s;
		for(long long i = 0; i < M; i++){
			cin >> u >> v >> s;
			G[u].push_back(edge(v, s, G[v].size()));
			G[v].push_back(edge(u, "0", G[u].size()-1));
			G[v].push_back(edge(u, s, G[u].size()));
			G[u].push_back(edge(v, "0", G[v].size()-1));
		}
		S = 1, T = N;
		
		poly ans, flow;
		while(1){
			for(long long i = 1; i <= T; i++) used[i] = false;
			flow = dfs(S, inf);
			if(flow <= zero) break;
			ans = ans + flow;
		}
		
		cout << ans.output() << endl;
	}
	
	return 0;
}
accuracy: 1
time_ms: 6060
memory_kb: 4608
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#define int long long
#define INF 1e9
#define MAX_V 505
using namespace std;
/*?????§?????¢?????´?????????(Ford_Fulerson????????¨)???O(F|E|)*/

//????????¨????§???????(???????????????????????????)
struct edge{
  int to;
  vector<int> cap;
  int rev;
};

vector<edge> G[MAX_V]; //??°???????????£??\?????????
bool used[MAX_V];      //DFS??§?????§??????????????????????????°

//from??????to??????????????????cap???????????°?????????????????????
void add_edge(int from,int to,vector<int> &cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,vector<int>((int)cap.size(),0),(int)G[from].size()-1});  
}

bool check(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]!=0) return A[i]>0;
  return false;
}

bool check2(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]==INF) return false;
  return true;
}

void Minus(vector<int> &res, vector<int> &v){
  assert(res.size()==v.size());
  for(int i=0;i<res.size();i++) res[i]-=v[i];
}

void Plus(vector<int> &res, vector<int> &v){
  assert(res.size()==v.size());
  for(int i=0;i<res.size();i++) res[i]+=v[i];
}

vector<int> Min(vector<int> &A, vector<int> &B){
  assert(A.size()==B.size());
  for(int i=0;i<A.size();i++){
    if(A[i]<B[i]) return A;
    if(A[i]>B[i]) return B;
  }
  return A;
}

/*bool isallnotINF(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]>=INF) return false;
  return true;
  }*/

//?¢?????????????DFS??§??¢???
vector<int> dfs(int v,int t,vector<int> f){
  if(v == t)return f;
  used[v]=true;
  for(int i=0; i<G[v].size() ;i++){
    edge &e = G[v][i];
    if(!used[e.to] && check(e.cap) ){
      vector<int> d = dfs(e.to ,t , Min(f,e.cap));
      assert(d.size()==f.size());
      //assert(isallnotINF(e.cap));
      /*      for(int j=0;j<d.size();j++){
	cout<<j<<' '<<d[j]<<endl;
	assert(d[j]!=INF);
	}*/
      
      if(check(d)&&check2(d)){
	Minus(e.cap, d);
	Plus(G[e.to][e.rev].cap, d);
	return d;
      }
    }
  }
  return vector<int>((int)f.size(),0);
}

bool isall0(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]!=0) return false;
  return true;
}

int V=55;

//s??????t???????????§???????±???????
vector<int> max_flow(int s,int t){
  vector<int> flow = vector<int>(V,0);
  for(;;){
    memset(used,0,sizeof(used));
    vector<int> r=vector<int>(V,0);
    r[0]=INF;
    vector<int> f = dfs(s, t, r);
    if(isall0(f)) return flow;
    /*if(isallnotINF(f)) */Plus(flow, f);
  }
}

vector<int> tov(string s){
  
  vector<int> res = vector<int>(V,0);
  
  int num1, num2, p=0;
  
  if('0'<=s[p]&&s[p]<='9'){
    num1=0;
    while('0'<=s[p]&&s[p]<='9') num1=num1*10+s[p++]-'0';
  }else num1=1;
  
  if(p==s.size()){
    num2=0;
  }else{
    if(p+1==s.size()) num2=1;
    else{
      //assert(s[p+1]=='^'&&('0'<=s[p+2]&&s[p+2]<='9'));
      p+=2;
      num2=0;
      while('0'<=s[p]&&s[p]<='9') num2=num2*10+s[p++]-'0';
    }
  }
  
  res[num2]=num1;
  
  return res;
}

vector<int> tocap(string s){
  
  vector<int> res = vector<int>(V,0);
  s+='+';
  
  string t;
  
  for(int i=0;i<s.size();i++){
    if(s[i]=='+'){
      vector<int> r=tov(t);
      Plus(res,r);
      t="";
    }else t+=s[i];
  }
  
  reverse(res.begin(), res.end());
  
  return res;
}

string itos(int num){

  string res;
  
  while(num){
    res=(char)(num%10+'0')+res;
    num/=10;
  }
  
  return res;
}

void output(vector<int> ans){
  
  reverse(ans.begin(), ans.end());
  
  string s;
  int flag=0;
  
  for(int i=ans.size()-1;i>=0;i--){
    if(ans[i]==0) continue;
    if(flag) s+="+";
    flag=1;
    if(i==0||(i!=0&&ans[i]!=1)) s+=itos(ans[i]);
    if(i==1) s+="x";
    else if(i) s+="x^", s+=itos(i);
  }
  if(s=="") s="0";
  cout<<s<<endl;
}

signed main(){
    
  int n, m;

  while(1){
    
    cin>>n>>m;
    if(!n&&!m) break;
    
    int a, b;
    string s;
    
    for(int i=0;i<m;i++){
      cin>>a>>b>>s;
      vector<int> cap=tocap(s);
      add_edge(a-1,b-1,cap);
      add_edge(b-1,a-1,cap);
    }
    assert(0!=n-1);
    output(max_flow(0,n-1));
    
    for(int i=0;i<MAX_V;i++) G[i].clear();
  }
  
  return 0;
}
accuracy: 1
time_ms: 6080
memory_kb: 3940
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#define int long long
#define INF 1e4
#define MAX_V 505
using namespace std;
/*?????§?????¢?????´?????????(Ford_Fulerson????????¨)???O(F|E|)*/

//????????¨????§???????(???????????????????????????)
struct edge{
  int to;
  vector<int> cap;
  int rev;
};

vector<edge> G[MAX_V]; //??°???????????£??\?????????
bool used[MAX_V];      //DFS??§?????§??????????????????????????°

//from??????to??????????????????cap???????????°?????????????????????
void add_edge(int from,int to,vector<int> &cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,vector<int>((int)cap.size(),0),(int)G[from].size()-1});  
}

bool check(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]!=0) return A[i]>0;
  return false;
}

bool check2(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]==INF) return false;
  return true;
}

void Minus(vector<int> &res, vector<int> &v){
  assert(res.size()==v.size());
  for(int i=0;i<res.size();i++) res[i]-=v[i];
}

void Plus(vector<int> &res, vector<int> &v){
  assert(res.size()==v.size());
  for(int i=0;i<res.size();i++) res[i]+=v[i];
}

vector<int> Min(vector<int> &A, vector<int> &B){
  assert(A.size()==B.size());
  for(int i=0;i<A.size();i++){
    if(A[i]<B[i]) return A;
    if(A[i]>B[i]) return B;
  }
  return A;
}

//?¢?????????????DFS??§??¢???
vector<int> dfs(int v,int t,vector<int> f){
  if(v == t)return f;
  used[v]=true;
  for(int i=0; i<G[v].size() ;i++){
    edge &e = G[v][i];
    if(!used[e.to] && check(e.cap) ){
      vector<int> d = dfs(e.to ,t , Min(f,e.cap));
      assert(d.size()==f.size());
      /*      for(int j=0;j<d.size();j++){
	cout<<j<<endl;
	assert(d[j]!=INF);
	}*/
      
      if(check(d)&&check2(d)){
	Minus(e.cap, d);
	Plus(G[e.to][e.rev].cap, d);
	return d;
      }
    }
  }
  return vector<int>((int)f.size(),0);
}

bool isall0(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]!=0) return false;
  return true;
}

bool isallnotINF(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]>=INF) return false;
  return true;
}

int V=55;

//s??????t???????????§???????±???????
vector<int> max_flow(int s,int t){
  vector<int> flow = vector<int>(V,0);
  for(;;){
    memset(used,0,sizeof(used));
    vector<int> r=vector<int>(V,0);
    r[0]=INF;
    vector<int> f = dfs(s, t, r);
    if(isall0(f)) return flow;
    /*if(isallnotINF(f)) */Plus(flow, f);
  }
}

vector<int> tov(string s){
  
  vector<int> res = vector<int>(V,0);
  
  int num1, num2, p=0;
  
  if('0'<=s[p]&&s[p]<='9'){
    num1=0;
    while('0'<=s[p]&&s[p]<='9') num1=num1*10+s[p++]-'0';
  }else num1=1;
  
  if(p==s.size()){
    num2=0;
  }else{
    if(p+1==s.size()) num2=1;
    else{
      //assert(s[p+1]=='^'&&('0'<=s[p+2]&&s[p+2]<='9'));
      p+=2;
      num2=0;
      while('0'<=s[p]&&s[p]<='9') num2=num2*10+s[p++]-'0';
    }
  }
  
  res[num2]=num1;
  
  return res;
}

vector<int> tocap(string s){
  
  vector<int> res = vector<int>(V,0);
  s+='+';
  
  string t;
  
  for(int i=0;i<s.size();i++){
    if(s[i]=='+'){
      vector<int> r=tov(t);
      Plus(res,r);
      t="";
    }else t+=s[i];
  }
  
  reverse(res.begin(), res.end());
  
  return res;
}

string itos(int num){

  string res;
  
  while(num){
    res=(char)(num%10+'0')+res;
    num/=10;
  }
  
  return res;
}

void output(vector<int> ans){
  
  reverse(ans.begin(), ans.end());
  
  string s;
  int flag=0;
  
  for(int i=ans.size()-1;i>=0;i--){
    if(ans[i]==0) continue;
    if(flag) s+="+";
    flag=1;
    if(i==0||(i!=0&&ans[i]!=1)) s+=itos(ans[i]);
    if(i==1) s+="x";
    else if(i) s+="x^", s+=itos(i);
  }
  if(s=="") s="0";
  cout<<s<<endl;
}

signed main(){
    
  int n, m;

  while(1){
    
    cin>>n>>m;
    if(!n&&!m) break;
    
    int a, b;
    string s;
    
    for(int i=0;i<m;i++){
      cin>>a>>b>>s;
      vector<int> cap=tocap(s);
      add_edge(a-1,b-1,cap);
      add_edge(b-1,a-1,cap);
    }
    assert(0!=n-1);
    output(max_flow(0,n-1));
    
    for(int i=0;i<MAX_V;i++) G[i].clear();
  }
  
  return 0;
}
accuracy: 1
time_ms: 5990
memory_kb: 4016
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define int long long
#define INF 1e4
#define MAX_V 505
using namespace std;
/*?????§?????¢?????´?????????(Ford_Fulerson????????¨)???O(F|E|)*/

//????????¨????§???????(???????????????????????????)
struct edge{
  int to;
  vector<int> cap;
  int rev;
};

vector<edge> G[MAX_V]; //??°???????????£??\?????????
bool used[MAX_V];      //DFS??§?????§??????????????????????????°

//from??????to??????????????????cap???????????°?????????????????????
void add_edge(int from,int to,vector<int> &cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,vector<int>((int)cap.size(),0),(int)G[from].size()-1});  
}

bool check(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]!=0) return A[i]>0;
  return false;
}

bool check2(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]==INF) return false;
  return true;
}

void Minus(vector<int> &res, vector<int> &v){
  assert(res.size()==v.size());
  for(int i=0;i<res.size();i++) res[i]-=v[i];
}

void Plus(vector<int> &res, vector<int> &v){
  assert(res.size()==v.size());
  for(int i=0;i<res.size();i++) res[i]+=v[i];
}

vector<int> Min(vector<int> &A, vector<int> &B){
  assert(A.size()==B.size());
  for(int i=0;i<A.size();i++){
    if(A[i]<B[i]) return A;
    if(A[i]>B[i]) return B;
  }
  return A;
}

//?¢?????????????DFS??§??¢???
vector<int> dfs(int v,int t,vector<int> f){
  if(v == t)return f;
  used[v]=true;
  for(int i=0; i<G[v].size() ;i++){
    edge &e = G[v][i];
    if(!used[e.to] && check(e.cap) ){
      vector<int> d = dfs(e.to ,t , Min(f,e.cap));
      
      /*      for(int j=0;j<d.size();j++){
	cout<<j<<endl;
	assert(d[j]!=INF);
	}*/
      
      if(check(d)&&check2(d)){
	Minus(e.cap, d);
	Plus(G[e.to][e.rev].cap, d);
	return d;
      }
    }
  }
  return vector<int>((int)f.size(),0);
}

bool isall0(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]!=0) return false;
  return true;
}

bool isallnotINF(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]>=INF) return false;
  return true;
}

int V=55;

//s??????t???????????§???????±???????
vector<int> max_flow(int s,int t){
  vector<int> flow = vector<int>(V,0);
  for(;;){
    memset(used,0,sizeof(used));
    vector<int> r=vector<int>(V,0);
    r[0]=INF;
    vector<int> f = dfs(s, t, r);
    if(isall0(f)) return flow;
    /*if(isallnotINF(f)) */Plus(flow, f);
  }
}

vector<int> tov(string s){
  
  vector<int> res = vector<int>(V,0);
  
  int num1, num2, p=0;
  
  if('0'<=s[p]&&s[p]<='9'){
    num1=0;
    while('0'<=s[p]&&s[p]<='9') num1=num1*10+s[p++]-'0';
  }else num1=1;
  
  if(p==s.size()){
    num2=0;
  }else{
    if(p+1==s.size()) num2=1;
    else{
      //assert(s[p+1]=='^'&&('0'<=s[p+2]&&s[p+2]<='9'));
      p+=2;
      num2=0;
      while('0'<=s[p]&&s[p]<='9') num2=num2*10+s[p++]-'0';
    }
  }
  
  res[num2]=num1;
  
  return res;
}

vector<int> tocap(string s){
  
  vector<int> res = vector<int>(V,0);
  s+='+';
  
  string t;
  
  for(int i=0;i<s.size();i++){
    if(s[i]=='+'){
      vector<int> r=tov(t);
      Plus(res,r);
      t="";
    }else t+=s[i];
  }
  
  reverse(res.begin(), res.end());
  
  return res;
}

string itos(int num){

  string res;
  
  while(num){
    res=(char)(num%10+'0')+res;
    num/=10;
  }
  
  return res;
}

void output(vector<int> ans){
  
  reverse(ans.begin(), ans.end());
  
  string s;
  int flag=0;
  
  for(int i=ans.size()-1;i>=0;i--){
    if(ans[i]==0) continue;
    if(flag) s+="+";
    flag=1;
    if(i==0||(i!=0&&ans[i]!=1)) s+=itos(ans[i]);
    if(i==1) s+="x";
    else if(i) s+="x^", s+=itos(i);
  }
  if(s=="") s="0";
  cout<<s<<endl;
}

signed main(){
    
  int n, m;

  while(1){
    
    cin>>n>>m;
    if(!n&&!m) break;
    
    int a, b;
    string s;
    
    for(int i=0;i<m;i++){
      cin>>a>>b>>s;
      vector<int> cap=tocap(s);
      add_edge(a-1,b-1,cap);
      add_edge(b-1,a-1,cap);
    }
    assert(0!=n-1);
    output(max_flow(0,n-1));
    
    for(int i=0;i<MAX_V;i++) G[i].clear();
  }
  
  return 0;
}
accuracy: 1
time_ms: 5980
memory_kb: 3900
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define int long long
#define INF 1e4
#define MAX_V 505
using namespace std;
/*?????§?????¢?????´?????????(Ford_Fulerson????????¨)???O(F|E|)*/

//????????¨????§???????(???????????????????????????)
struct edge{
  int to;
  vector<int> cap;
  int rev;
};

vector<edge> G[MAX_V]; //??°???????????£??\?????????
bool used[MAX_V];      //DFS??§?????§??????????????????????????°

//from??????to??????????????????cap???????????°?????????????????????
void add_edge(int from,int to,vector<int> &cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,vector<int>((int)cap.size(),0),(int)G[from].size()-1});  
}

bool check(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]!=0) return A[i]>0;
  return false;
}

bool check2(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]==INF) return false;
  return true;
}

void Minus(vector<int> &res, vector<int> &v){
  for(int i=0;i<res.size();i++) res[i]-=v[i];
}

void Plus(vector<int> &res, vector<int> &v){
  for(int i=0;i<res.size();i++) res[i]+=v[i];
}

vector<int> Min(vector<int> &A, vector<int> &B){
  for(int i=0;i<A.size();i++){
    if(A[i]<B[i]) return A;
    if(A[i]>B[i]) return B;
  }
  return A;
}

//?¢?????????????DFS??§??¢???
vector<int> dfs(int v,int t,vector<int> f){
  if(v == t)return f;
  used[v]=true;
  for(int i=0; i<G[v].size() ;i++){
    edge &e = G[v][i];
    if(!used[e.to] && check(e.cap) ){
      vector<int> d = dfs(e.to ,t , Min(f,e.cap));
      if(check(d)&&check2(d)){
	Minus(e.cap, d);
	Plus(G[e.to][e.rev].cap, d);
	return d;
      }
    }
  }
  return vector<int>((int)f.size(),0);
}

bool isall0(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]!=0) return false;
  return true;
}

bool isallnotINF(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]>=INF) return false;
  return true;
}

int V=55;

//s??????t???????????§???????±???????
vector<int> max_flow(int s,int t){
  vector<int> flow = vector<int>(V,0);
  for(;;){
    memset(used,0,sizeof(used));
    vector<int> r=vector<int>(V,0);
    r[0]=INF;
    vector<int> f = dfs(s, t, r);
    if(isall0(f)) return flow;
    /*if(isallnotINF(f)) */Plus(flow, f);
  }
}

vector<int> tov(string s){
  
  vector<int> res = vector<int>(V,0);
  
  int num1, num2, p=0;
  
  if('0'<=s[p]&&s[p]<='9'){
    num1=0;
    while('0'<=s[p]&&s[p]<='9') num1=num1*10+s[p++]-'0';
  }else num1=1;
  
  if(p==s.size()){
    num2=0;
  }else{
    if(p+1==s.size()) num2=1;
    else{
      //assert(s[p+1]=='^'&&('0'<=s[p+2]&&s[p+2]<='9'));
      p+=2;
      num2=0;
      while('0'<=s[p]&&s[p]<='9') num2=num2*10+s[p++]-'0';
    }
  }
  
  res[num2]=num1;
  
  return res;
}

vector<int> tocap(string s){
  
  vector<int> res = vector<int>(V,0);
  s+='+';
  
  string t;
  
  for(int i=0;i<s.size();i++){
    if(s[i]=='+'){
      vector<int> r=tov(t);
      Plus(res,r);
      t="";
    }else t+=s[i];
  }
  
  reverse(res.begin(), res.end());
  
  return res;
}

string itos(int num){

  string res;
  
  while(num){
    res=(char)(num%10+'0')+res;
    num/=10;
  }
  
  return res;
}

void output(vector<int> ans){
  
  reverse(ans.begin(), ans.end());
  
  string s;
  int flag=0;
  
  for(int i=ans.size()-1;i>=0;i--){
    if(ans[i]==0) continue;
    if(flag) s+="+";
    flag=1;
    if(i==0||(i!=0&&ans[i]!=1)) s+=itos(ans[i]);
    if(i==1) s+="x";
    else if(i) s+="x^", s+=itos(i);
  }
  if(s=="") s="0";
  cout<<s<<endl;
}

signed main(){
    
  int n, m;

  while(1){
    
    cin>>n>>m;
    if(!n&&!m) break;
    
    int a, b;
    string s;
    
    for(int i=0;i<m;i++){
      cin>>a>>b>>s;
      vector<int> cap=tocap(s);
      add_edge(a-1,b-1,cap);
      add_edge(b-1,a-1,cap);
    }
    assert(0!=n-1);
    output(max_flow(0,n-1));
    
    for(int i=0;i<MAX_V;i++) G[i].clear();
  }
  
  return 0;
}
accuracy: 1
time_ms: 6110
memory_kb: 3792
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#define int long long
#define INF 1e4
#define MAX_V 505
using namespace std;
/*?????§?????¢?????´?????????(Ford_Fulerson????????¨)???O(F|E|)*/

//????????¨????§???????(???????????????????????????)
struct edge{
  int to;
  vector<int> cap;
  int rev;
};

vector<edge> G[MAX_V]; //??°???????????£??\?????????
bool used[MAX_V];      //DFS??§?????§??????????????????????????°

//from??????to??????????????????cap???????????°?????????????????????
void add_edge(int from,int to,vector<int> &cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,vector<int>((int)cap.size(),0),(int)G[from].size()-1});  
}

bool check(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]!=0) return A[i]>0;
  return false;
}

bool check2(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]==INF) return false;
  return true;
}

void Minus(vector<int> &res, vector<int> &v){
  for(int i=0;i<res.size();i++) res[i]-=v[i];
}

void Plus(vector<int> &res, vector<int> &v){
  for(int i=0;i<res.size();i++) res[i]+=v[i];
}

vector<int> Min(vector<int> &A, vector<int> &B){
  for(int i=0;i<A.size();i++){
    if(A[i]<B[i]) return A;
    if(A[i]>B[i]) return B;
  }
  return A;
}

//?¢?????????????DFS??§??¢???
vector<int> dfs(int v,int t,vector<int> f){
  if(v == t)return f;
  used[v]=true;
  for(int i=0; i<G[v].size() ;i++){
    edge &e = G[v][i];
    if(!used[e.to] && check(e.cap) ){
      vector<int> d = dfs(e.to ,t , Min(f,e.cap));
      if(check(d)&&check2(d)){
	Minus(e.cap, d);
	Plus(G[e.to][e.rev].cap, d);
	return d;
      }
    }
  }
  return vector<int>((int)f.size(),0);
}

bool isall0(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]!=0) return false;
  return true;
}

bool isallnotINF(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]>=INF) return false;
  return true;
}

int V=55;

//s??????t???????????§???????±???????
vector<int> max_flow(int s,int t){
  vector<int> flow = vector<int>(V,0);
  for(;;){
    memset(used,0,sizeof(used));
    vector<int> r=vector<int>(V,0);
    r[0]=INF;
    vector<int> f = dfs(s, t, r);
    if(isall0(f)) return flow;
    /*if(isallnotINF(f)) */Plus(flow, f);
  }
}

vector<int> tov(string s){
  
  vector<int> res = vector<int>(V,0);
  
  int num1, num2, p=0;
  
  if('0'<=s[p]&&s[p]<='9'){
    num1=0;
    while('0'<=s[p]&&s[p]<='9') num1=num1*10+s[p++]-'0';
  }else num1=1;
  
  if(p==s.size()){
    num2=0;
  }else{
    if(p+1==s.size()) num2=1;
    else{
      //assert(s[p+1]=='^'&&('0'<=s[p+2]&&s[p+2]<='9'));
      p+=2;
      num2=0;
      while('0'<=s[p]&&s[p]<='9') num2=num2*10+s[p++]-'0';
    }
  }
  
  res[num2]=num1;
  
  return res;
}

vector<int> tocap(string s){
  
  vector<int> res = vector<int>(V,0);
  s+='+';
  
  string t;
  
  for(int i=0;i<s.size();i++){
    if(s[i]=='+'){
      vector<int> r=tov(t);
      Plus(res,r);
      t="";
    }else t+=s[i];
  }
  
  reverse(res.begin(), res.end());
  
  return res;
}

string itos(int num){

  string res;
  
  while(num){
    res=(char)(num%10+'0')+res;
    num/=10;
  }
  
  return res;
}

void output(vector<int> ans){
  
  reverse(ans.begin(), ans.end());
  
  string s;
  int flag=0;
  
  for(int i=ans.size()-1;i>=0;i--){
    if(ans[i]==0) continue;
    if(flag) s+="+";
    flag=1;
    if(i==0||(i!=0&&ans[i]!=1)) s+=itos(ans[i]);
    if(i==1) s+="x";
    else if(i) s+="x^", s+=itos(i);
  }
  if(s=="") s="0";
  cout<<s<<endl;
}

signed main(){
    
  int n, m;

  while(1){
    
    cin>>n>>m;
    if(!n&&!m) break;
    
    int a, b;
    string s;
    
    for(int i=0;i<m;i++){
      cin>>a>>b>>s;
      vector<int> cap=tocap(s);
      add_edge(a-1,b-1,cap);
      add_edge(b-1,a-1,cap);
    }
    
    output(max_flow(0,n-1));
    
    for(int i=0;i<MAX_V;i++) G[i].clear();
  }
  
  return 0;
}
accuracy: 1
time_ms: 6110
memory_kb: 3864
final_rank: 15

code_snippet: #include <bits/stdc++.h>
#define int long long
#define INF 1e4
#define MAX_V 505
using namespace std;
/*?????§?????¢?????´?????????(Ford_Fulerson????????¨)???O(F|E|)*/

//????????¨????§???????(???????????????????????????)
struct edge{
  int to;
  vector<int> cap;
  int rev;
};

vector<edge> G[MAX_V]; //??°???????????£??\?????????
bool used[MAX_V];      //DFS??§?????§??????????????????????????°

//from??????to??????????????????cap???????????°?????????????????????
void add_edge(int from,int to,vector<int> &cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,vector<int>((int)cap.size(),0),(int)G[from].size()-1});  
}

bool check(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]!=0) return A[i]>0;
  return false;
}

bool check2(vector<int> &A){
  for(int i=0;i<A.size();i++)
    if(A[i]==INF) return false;
  return true;
}

void Minus(vector<int> &res, vector<int> &v){
  for(int i=0;i<res.size();i++) res[i]-=v[i];
}

void Plus(vector<int> &res, vector<int> &v){
  for(int i=0;i<res.size();i++) res[i]+=v[i];
}

vector<int> Min(vector<int> &A, vector<int> &B){
  for(int i=0;i<A.size();i++){
    if(A[i]<B[i]) return A;
    if(A[i]>B[i]) return B;
  }
  return A;
}

//?¢?????????????DFS??§??¢???
vector<int> dfs(int v,int t,vector<int> f){
  if(v == t)return f;
  used[v]=true;
  for(int i=0; i<G[v].size() ;i++){
    edge &e = G[v][i];
    if(!used[e.to] && check(e.cap) ){
      vector<int> d = dfs(e.to ,t , Min(f,e.cap));
      if(check(d)&&check2(d)){
	Minus(e.cap, d);
	Plus(G[e.to][e.rev].cap, d);
	return d;
      }
    }
  }
  return vector<int>((int)f.size(),0);
}

bool isall0(vector<int> &v){
  for(int i=0;i<v.size();i++)
    if(v[i]!=0) return false;
  return true;
}

int V=55;

//s??????t???????????§???????±???????
vector<int> max_flow(int s,int t){
  vector<int> flow = vector<int>(V,0);
  for(;;){
    memset(used,0,sizeof(used));
    vector<int> f = dfs(s, t, vector<int>(V,INF));
    if(isall0(f)) return flow;
    Plus(flow, f);
  }
}

vector<int> tov(string s){
  
  vector<int> res = vector<int>(V,0);
  
  int num1, num2, p=0;
  
  if('0'<=s[p]&&s[p]<='9'){
    num1=0;
    while('0'<=s[p]&&s[p]<='9') num1=num1*10+s[p++]-'0';
  }else num1=1;
  
  if(p==s.size()){
    num2=0;
  }else{
    if(p+1==s.size()) num2=1;
    else{
      //assert(s[p+1]=='^'&&('0'<=s[p+2]&&s[p+2]<='9'));
      p+=2;
      num2=0;
      while('0'<=s[p]&&s[p]<='9') num2=num2*10+s[p++]-'0';
    }
  }
  
  res[num2]=num1;
  
  return res;
}

vector<int> tocap(string s){
  
  vector<int> res = vector<int>(V,0);
  s+='+';
  
  string t;
  
  for(int i=0;i<s.size();i++){
    if(s[i]=='+'){
      vector<int> r=tov(t);
      Plus(res,r);
      t="";
    }else t+=s[i];
  }
  
  reverse(res.begin(), res.end());
  
  return res;
}

string itos(int num){

  string res;
  
  while(num){
    res=(char)(num%10+'0')+res;
    num/=10;
  }
  
  return res;
}

void output(vector<int> ans){
  
  reverse(ans.begin(), ans.end());
  
  string s;
  int flag=0;
  
  for(int i=ans.size()-1;i>=0;i--){
    if(ans[i]==0) continue;
    if(flag) s+="+";
    flag=1;
    if(i==0||(i!=0&&ans[i]!=1)) s+=itos(ans[i]);
    if(i==1) s+="x";
    else if(i) s+="x^", s+=itos(i);
  }
  if(s=="") s="0";
  cout<<s<<endl;
}

signed main(){
    
  int n, m;

  while(1){
    
    cin>>n>>m;
    if(!n&&!m) break;
    
    int a, b;
    string s;
    
    for(int i=0;i<m;i++){
      cin>>a>>b>>s;
      vector<int> cap=tocap(s);
      add_edge(a-1,b-1,cap);
      add_edge(b-1,a-1,cap);
    }
    
    output(max_flow(0,n-1));
    
    for(int i=0;i<MAX_V;i++) G[i].clear();
  }
  
  return 0;
}
accuracy: 1
time_ms: 6090
memory_kb: 3924
final_rank: 16