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

u1 v1 p1

...

uM vM pM

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

Each polynomial has the form of:

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

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

each term aixi (for i ≥ 2) is represented as <ai>x^<i>

the linear term (a1x) is represented as <a1>x;

the constant (a0) is represented just by digits;

these terms are given in the strictly decreasing order of the degrees and connected by a
plus sign ("+");

just like the standard notations, the <ai> is omitted if ai = 1 for non-constant terms;

similarly, the entire term is omitted if ai = 0 for any terms; and

the polynomial representations contain no space or characters other than digits, "x", "^", and "+".

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

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

Output

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

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

Solution in C (judge verdict: Accepted)

// AOJ 2328 Mobile Network
// 2018.3.13 bal4u

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define INF      0x01010101
#define CZ       0
#define CINF     1

#define VMAX 53
typedef struct { int to; short cap; int rev; } EDGE;
EDGE edge[VMAX][VMAX]; int hi[VMAX];
int V;				// 頂点数
int level[VMAX], iter[VMAX];
int queue[2*VMAX], qtop;

typedef struct { char w; short c[55]; } CAP;
CAP cap[15000]; int cid;

char buf[600], *p;
int in()
{
	int n = 0;
	while (isdigit(*p)) n = 10*n + (*p++ & 0xf);
	p++;
	return n;
}

int cap_new() { int id = cid++;	cap[id].w = 1, cap[id].c[0] = 0; return id; }
void cap_set(int id1, int id2) { memcpy(cap+id1, cap+id2, sizeof(CAP)); }

void cap_norm(int id)
{
	int w = cap[id].w - 1;
	while (w > 0 && cap[id].c[w] == 0) w--;
	cap[id].w = w + 1;
}

int cap_zero(int id) { return cap[id].c[cap[id].w-1]; }

int cap_cmp(int id1, int id2)
{
	int i, w1 = cap[id1].w-1, w2 = cap[id2].w-1;
	if (w1 > w2) return  cap[id1].c[w1];
	if (w2 > w1) return  -cap[id2].c[w2];
	for (i = w1; i >= 0; i--) {
		if (cap[id1].c[i] != cap[id2].c[i]) return cap[id1].c[i] - cap[id2].c[i];
	}
	return 0;
}

void cap_add(int id1, int id2)
{
	int i, w1 = cap[id1].w, w2 = cap[id2].w;
	if (w1 > w2) {
		for (i = 0; i < w2; i++) cap[id1].c[i] += cap[id2].c[i];
	} else {
		for (i = 0; i < w1; i++) cap[id1].c[i] += cap[id2].c[i];
		for (     ; i < w2; i++) cap[id1].c[i]  = cap[id2].c[i];
		cap[id1].w = cap[id2].w;
		cap_norm(id1);
	}
}

void cap_sub(int id1, int id2)
{
	int i, w1 = cap[id1].w, w2 = cap[id2].w;
	if (w1 > w2) {
		for (i = 0; i < w2; i++) cap[id1].c[i] -= cap[id2].c[i];
	} else {
		for (i = 0; i < w1; i++) cap[id1].c[i] -= cap[id2].c[i];
		for (     ; i < w2; i++) cap[id1].c[i] = -cap[id2].c[i];
		cap[id1].w = cap[id2].w;
		cap_norm(id1);
	}
}

void str2cap(int id)
{
	int c, e, w = 0;

	while (*p > ' ') {
		if (*p == '+') p++;
		c = 1; if (isdigit(*p)) c = in(), p--;
		e = 0; if (*p == 'x') {
			p++; e = 1;
			if (*p == '^') { p++; if (isdigit(*p)) e = in(), p--; }
		}
		cap[id].c[e] = c;
		if (e > w) w = e;
	}
	cap[id].w = w+1;
}

void coutcap(int id)
{
	int f = 0, i, w = cap[id].w-1;

	for (i = w; i > 0; i--) {
		if (cap[id].c[i] == 0) continue;
		if (f) putchar('+');
		if (cap[id].c[i] != 1) printf("%d", cap[id].c[i]);
		putchar('x'); f = 1;
		if (i > 1) printf("^%d", i);
	}
	if (!f) printf("%d", cap[id].c[0]);
	else if (cap[id].c[0]) printf("+%d", cap[id].c[0]);
	putchar('\n');
}

void add_edge(int from, int to, int id)
{
	int f, t, c;
	EDGE *e;

	f = hi[from]++, t = hi[to]++;
	e = &edge[from][f], e->to = to, e->cap = id, e->rev = t;
	c = cap_new(), cap_set(c, id);
	e = &edge[to][t], e->to = from, e->cap = c, e->rev = f;
}

void bfs(int s)
{
	int i, v;
	EDGE *e;
	
	memset(level, -1, V << 2);
	level[s] = 0;
	queue[0] = s, qtop =1;
	while (qtop) {
		v = queue[--qtop];
		for (i = 0; i < hi[v]; i++) {
			e = &edge[v][i];
			if (cap_zero(e->cap) > 0 && level[e->to] < 0) {
				level[e->to] = level[v] + 1;
				queue[qtop++] = e->to;
			}
		}
	}
}
 
int dfs(int v, int t, int f)
{
	int *i, d, ff;
	EDGE *e;
	
	ff = cap_new(); cap_set(ff, f);
	if (v == t) return ff;
	d = cap_new();
	for (i = &iter[v]; *i < hi[v]; (*i)++) {
		e = &edge[v][*i];
		if (cap_zero(e->cap) > 0 && level[v] < level[e->to]) {
			if (cap_cmp(ff, e->cap) <= 0) cap_set(d, dfs(e->to, t, ff));
			else                          cap_set(d, dfs(e->to, t, e->cap));
			if (cap_zero(d) > 0) {
				cap_sub(e->cap, d);
				cap_add(edge[e->to][e->rev].cap, d);
				return d;
			}
		}
	}
	return CZ;
}
 
int maxFlow(int s, int t)
{
	int f =	cap_new();
	int flow = cap_new();

	while (1) {
		bfs(s);
		if (level[t] < 0) break;
		memset(iter, 0, V << 2);
		while (1) {
			cap_set(f, dfs(s, t, CINF));
			if (cap_zero(f) <= 0) break;
			cap_add(flow, f);
		}
	}
	return flow;
}

int main()
{
	int N, M, i, u, v;

	while (fgets(p=buf, 10, stdin) && *p != '0') {
		memset(cap, 0, sizeof(cap));
		cap[CZ].w = 1, cap[CZ].c[0] = 0;
		cap[CINF].w = 53, cap[CINF].c[52] = 1;
		cid = 2;

		N = in(), M = in();
		V = N; memset(hi, 0, V << 2);

		for (i = 0; i < M; i++) {
			fgets(p=buf, 600, stdin);
			u = in()-1, v = in()-1;
			str2cap(cid++);
			add_edge(u, v, cid-1);
		}
		coutcap(maxFlow(0, N-1));
	}
	return 0;
}