You are given $n$ blocks, each of them is of the form [color$_1$|value|color$_2$], where the block can also be flipped to get [color$_2$|value|color$_1$]. 

A sequence of blocks is called valid if the touching endpoints of neighboring blocks have the same color. For example, the sequence of three blocks A, B and C is valid if the left color of the B is the same as the right color of the A and the right color of the B is the same as the left color of C.

The value of the sequence is defined as the sum of the values of the blocks in this sequence.

Find the maximum possible value of the valid sequence that can be constructed from the subset of the given blocks. The blocks from the subset can be reordered and flipped if necessary. Each block can be used at most once in the sequence.


-----Input-----

The first line of input contains a single integer $n$ ($1 \le n \le 100$) — the number of given blocks.

Each of the following $n$ lines describes corresponding block and consists of $\mathrm{color}_{1,i}$, $\mathrm{value}_i$ and $\mathrm{color}_{2,i}$ ($1 \le \mathrm{color}_{1,i}, \mathrm{color}_{2,i} \le 4$, $1 \le \mathrm{value}_i \le 100\,000$).


-----Output-----

Print exactly one integer — the maximum total value of the subset of blocks, which makes a valid sequence.


-----Examples-----
Input
6
2 1 4
1 2 4
3 4 4
2 8 3
3 16 3
1 32 2

Output
63
Input
7
1 100000 1
1 100000 2
1 100000 2
4 50000 3
3 50000 4
4 50000 4
3 50000 3

Output
300000
Input
4
1 1000 1
2 500 2
3 250 3
4 125 4

Output
1000


-----Note-----

In the first example, it is possible to form a valid sequence from all blocks.

One of the valid sequences is the following:

[4|2|1] [1|32|2] [2|8|3] [3|16|3] [3|4|4] [4|1|2]

The first block from the input ([2|1|4] $\to$ [4|1|2]) and second ([1|2|4] $\to$ [4|2|1]) are flipped.

In the second example, the optimal answers can be formed from the first three blocks as in the following (the second or the third block from the input is flipped):

[2|100000|1] [1|100000|1] [1|100000|2]

In the third example, it is not possible to form a valid sequence of two or more blocks, so the answer is a sequence consisting only of the first block since it is the block with the largest value.

Difficulty: interview

Starter code:

Solutions:
#      
import collections, atexit, math, sys, bisect 

sys.setrecursionlimit(1000000)
def getIntList():
    return list(map(int, input().split()))    

try :
    #raise ModuleNotFoundError
    import numpy
    def dprint(*args, **kwargs):
        print(*args, **kwargs, file=sys.stderr)
    dprint('debug mode')
except ModuleNotFoundError:
    def dprint(*args, **kwargs):
        pass



inId = 0
outId = 0
if inId>0:
    dprint('use input', inId)
    sys.stdin = open('input'+ str(inId) + '.txt', 'r') #标准输出重定向至文件
if outId>0:
    dprint('use output', outId)
    sys.stdout = open('stdout'+ str(outId) + '.txt', 'w') #标准输出重定向至文件
    atexit.register(lambda :sys.stdout.close())     #idle 中不会执行 atexit
    
N, = getIntList()

zb = []
 
total = 0

de = [0,0,0,0,0]
gr = [ [] for i in range(5)]
minv = 10000000
for i in range(N):
    a,b,c = getIntList()
    de[a]+=1
    de[c] +=1
    zb.append( (a,b,c) )
    total +=b
    if a!=c:
        minv = min(minv,b)
vis = [0,0,0,0,0]

def dfs( root):
    if vis[root]:return []
    vis[root] = 1
    r = [root,]
    for x in zb:
        a,b,c =  x
        if a==root:
            r = r+ dfs(c)
        elif c==root:
            r = r+ dfs(a)
    return r

res = 0
for i in range(1,5):
    if vis[i]:continue
    t = dfs(i)
    t = set(t)
    if len(t) ==4:
        for j in range(1,5):
            if de[j]%2==0:
                print(total)
                return
        print(total-minv)
        return
    tr = 0
    for x in zb:
        a,b,c = x
        if a in t:
            tr +=b
    res = max(res,tr)

print(res)
 







n=int(input())
mv = 10**9
f = [0 for i in range(4)]
adj = [[i == j for j in range(4)] for i in range(4)]
w = [0 for i in range(4)]
for _ in range(n):
 a,v,b=map(int,input().split())
 a-=1
 b-=1
 if a!=b: mv = min(mv, v)
 f[a]^=1
 f[b]^=1
 w[a] += v
 adj[a][b] = adj[b][a] = True
for k in range(4):
 for i in range(4):
  for j in range(4):
   if adj[i][k] and adj[k][j]: adj[i][j] = True
if all(adj[0]) and all(f):
 print(sum(w) - mv)
else:
 print(max(sum(w[j] for j in range(4) if adj[i][j]) for i in range(4)))

class UnionFind():
	def __init__(self, size):
		self.table = [-1 for _ in range(size)]

	def find(self, x):
		if self.table[x] < 0:
			return x
		else:
			self.table[x] = self.find(self.table[x])
			return self.table[x]

	def union(self, x, y):
		s1 = self.find(x)
		s2 = self.find(y)
		if s1 != s2:
			if self.table[s1] > self.table[s2]:
				self.table[s2] = s1
			elif self.table[s1] < self.table[s2]:
				self.table[s1] = s2
			else:
				self.table[s1] = s2
				self.table[s2] -= 1
		return

n = int(input())
#d = [[[] for _ in range(4)] for _ in range(4)]
d = [[] for _ in range(4)]
uf = UnionFind(4)
CVC = [list(map(int, input().split())) for _ in range(n)]
vals = []
min_not_auto = float("inf")
for i in range(n):
	cvc = CVC[i]
	vals.append(cvc[1])
	#d[cvc[0] - 1][cvc[2] - 1] = cvc[1]
	#d[cvc[2] - 1][cvc[0] - 1] = cvc[1]
	d[cvc[0] - 1].append(cvc[1])
	d[cvc[2] - 1].append(cvc[1])
	if cvc[0] != cvc[2] and cvc[1] < min_not_auto:
		min_not_auto = cvc[1]
 
	uf.union(cvc[0] - 1, cvc[2] - 1)

root_num = 0
for i in range(4):
	if uf.table[i] < 0:
		root_num += 1

if root_num == 1:
	odd = True
	for i in range(4):
		if len(d[i]) % 2 == 0:
			odd = False
			break
	if odd:
		print(sum(vals) - min_not_auto)
	else:
		answers = [0] * 4
		for i in range(4):
			answers[uf.find(i)] += sum(d[i])
		print(max(answers) // 2)

else:
	answers = [0] * 4
	for i in range(4):
		answers[uf.find(i)] += sum(d[i])
	print(max(answers) // 2)


from random import randint

values = [[] for _ in range(10)]
types = [[0, 1, 2, 3], [1, 4, 5, 6], [2, 5, 7, 8], [3, 6, 8, 9]]
b = [1]*10
B = 128
for i in range(9):
    b[i+1] = b[i]*B

for i in range(4):
    values[types[i][i]].append(0)

n = int(input())
for _ in range(n):
    i, v, j = map(int,input().split())
    t = types[i-1][j-1]
    if i == j:
        values[t][0] += v
    else:
        values[t].append(v)


for i in range(4):
    for j in range(i+1,4):
        t = types[i][j]
        values[t].sort()
        while len(values[t])>3:
            v=values[t].pop()+ values[t].pop()
            values[t][-1]+= v
        values[t].sort(reverse = True)

cur=[{},{},{},{}]
m = 0
for i in range(4):
    for j in range(i,4):
        t = types[i][j]
        if values[t]:
            cur[i][b[t]] = values[t][0]
            m = max(m,values[t][0])

def cnt(k,t):
    return k//b[t]%B

for _ in range(n):
    next = [{},{},{},{}]
    for i in range(4):
        for j in range(4):
            t = types[i][j]
            for k, v in cur[i].items():
                c = cnt(k,t)
                if len(values[t])>c:
                    nk = k+b[t]
                    if nk not in next[j]:
                        next[j][nk] = values[t][c] + v
                        m = max(m, values[t][c] + v)
    cur = next

print (m)

def min(a, b):
    if a < b:
        return a
    return b
def max(a,b):
    return abs(min(-a,-b))
been = [0 for i in range(4)]
ans = 0
minw = 10**18
degpar = [0 for i in range(4)]
w = [0 for i in range(4)]
gr = [list() for i in range(4)]
rem = [[0 for i in range(4)] for j in range(4)]
def dfs(x, l):
    l.append(w[x])
    if been[x]:
        return
    been[x] = 1
    for i in gr[x]:
        if been[i] == 0 and rem[x][i] > 0:
            dfs(i, l)
n = int(input())
blocks = []
for i in range(n):
    a,v,b = list(map(int, input().split()))
    a -= 1
    b -= 1
    if a != b:
        blocks.append([a,v,b])
    w[b] += v
    if a != b:
        minw = min(minw, v)
    degpar[a] += 1
    degpar[a] %= 2
    degpar[b] += 1
    degpar[b] %= 2
    gr[a].append(b)
    gr[b].append(a)
    rem[a][b] += 1
    rem[b][a] += 1
ok = True
for i in range(4):
    l = []
    if been[i] == 0:
        dfs(i, l)
    if i == 0 and all(been) and all(degpar):
        ok = False
        break
    ans = max(ans, sum(l))
if ok:
    print(ans)
    return
for p in blocks:
    i = p[0]
    j = p[2]
    w[j] -= p[1]
    been = [0 for i in range(4)]
    rem[i][j] -= 1
    rem[j][i] -= 1
    #print(i)
    #print(j)
    #print(':')
    for x in range(4):
        l = []
        if been[x] == 0:
            dfs(x,l)
        ans = max(ans, sum(l))
        #print(sum(l))
    w[j] += p[1]
    rem[i][j] += 1
    rem[j][i] += 1
print(ans)


class Domino:
    def __init__(self,side1,side2,value,double,parts):
        self.side1=side1
        self.side2=side2
        self.value=value
        self.double=double #True/False
        self.parts=parts

    def __repr__(self):
        return str(self.side1)+'-'+str(self.side2)+'-'+str(self.double)+'-'+str(self.value)+'-'+'|'.join([str(i) for i in self.parts])

    def __add__(self, other):

        if self.side1==other.side2:
            return Domino(self.side2,other.side1,self.value+other.value, self.side2==other.side1,self.parts+other.parts)
        elif self.side1==other.side1:
            return Domino(self.side2,other.side2,self.value+other.value, self.side2==other.side2,self.parts+other.parts)
        elif self.side2==other.side2:
            return Domino(self.side1,other.side1,self.value+other.value, self.side1==other.side1,self.parts+other.parts)
        elif self.side2==other.side1:
            return Domino(self.side1,other.side2,self.value+other.value, self.side1==other.side2,self.parts+other.parts)
        else:
            return Domino(0,0,0,True,[-1])


def SortByValue(Domino):
    return Domino.value

def SortByDup(Domino):
    return Domino.double

def addbycolor(self, other, color):
    if self.side1 == color and other.side2 == color:
        return Domino(self.side2, other.side1, self.value + other.value, self.side2 == other.side1,
                      self.parts + other.parts)
    elif self.side1 == color and other.side1 == color:
        return Domino(self.side2, other.side2, self.value + other.value, self.side2 == other.side2,
                      self.parts + other.parts)
    elif self.side2 == color and other.side2 == color:
        return Domino(self.side1, other.side1, self.value + other.value, self.side1 == other.side1,
                      self.parts + other.parts)
    elif self.side2 == color and other.side1 == color:
        return Domino(self.side1, other.side2, self.value + other.value, self.side1 == other.side2,
                      self.parts + other.parts)
    else:
        raise Exception

def delcolor(l,num):

    p=1
    while p==1:
        p=0
        for i in range(len(l)-1):
            for j in range(i+1,len(l)):

                if (l[i].side1==num or l[i].side2==num) and (l[j].side1==num or l[j].side2==num):
                    a=l.pop(i)
                    b=l.pop(j-1)
                    ab=addbycolor(a,b,num)
                    l.append(ab)
                    p=1
                    l.sort(key=SortByValue)
                    l.sort(key=SortByDup)
                    l.reverse()
                    break
            if p==1:
                break

    l.sort(key=SortByValue)
    l.sort(key=SortByDup)
    l.reverse()
    return l

def getvalue(l):
    value=0
    for i in l:
        value+=i.value

n=int(input())
l=[]
l_dup=[]
for i in range(n):
    q,w,e=[int(el) for el in input().split()]
    if q==e+100:
        l_dup.append(Domino(q,e,w,q==e,[i]))

    else:
        l.append(Domino(q,e,w,q==e,[i]))

l.sort(key=SortByValue)
l.sort(key=SortByDup)
l.reverse()

out=0
s1=[1,2,3,4]
for i1 in s1:
    s2=s1.copy()
    s2.remove(i1)
    for i2 in s2:
        s3=s2.copy()
        s3.remove(i2)
        for i3 in s3:
            s4=s3.copy()
            s4.remove(i3)
            for i4 in s4:
#                l1_dup = l_dup.copy()
                l1 = l.copy()
                cc=len(l1)
                cont=1
                while cont==1:
                    cont=0
                    l1=delcolor(l1,i1)
#                    for d in l1:
#                        if d.side1==d.side2:
#                            l1_dup.append(d)
#                            l1.remove(d)
                    l1=delcolor(l1,i2)
#                    for d in l1:
#                        if d.side1==d.side2:
#                            l1_dup.append(d)
#                            l1.remove(d)
                    l1=delcolor(l1,i3)
#                    for d in l1:
#                        if d.side1==d.side2:
#                            l1_dup.append(d)
#                            l1.remove(d)
                    l1=delcolor(l1,i4)
#                    for d in l1:
#                        if d.side1==d.side2:
#                            l1_dup.append(d)
#                            l1.remove(d)
                    if len(l1)<cc:
                        cc=len(l1)
                        cont=1
            #l1[0] - наша линия
            #вставим дупли
#                for i in l1[0].parts:
#                    for j in l1_dup:
#                        if l[i].side1==j.side1 or l[i].side2==j:
#                            l1[0].value+=j.value
#                            aa=l1_dup.append(j)
                l1.sort(key=SortByValue)
                l1.reverse()
                out=max(out,l1[0].value)



print(out)