CodeEff/ECCO huggingface dataset:
# Original solution
class Tree:
    def __init__(self):
        self.id = 0
        self.p = -1
        self.depth = -1
        self.type = "leaf"
        self.len_c = 0
        self.c = []
    def __str__(self):
        return f"node {self.id}: parent = {self.p}, depth = {self.depth}, {self.type}, {self.c}"
n = int(eval(input()))
li = [Tree() for _ in range(n)]
for _ in range(n):
    id, k, *c = list(map(int, input().split()))
    if k == 0:
        c = []
    else:
        li[id].type = "internal node"
    li[id].id = id
    li[id].c = c
    for j in c:
        li[j].p = id
root = 0
while True:
    a = li[root].p
    if a == -1:
        li[root].type = "root"
        li[root].depth = 0
        break
    root = a
dp = [(root, 0)]
while dp:
    id, d = dp.pop()
    for i in li[id].c:
        li[i].depth = d + 1
        dp.append((i, d + 1))
for i in range(n):
    print((li[i]))



# Optimized solution
import sys
readline = sys.stdin.readline
class Tree:
    def __init__(self):
        self.id = 0
        self.p = -1
        self.depth = -1
        self.type = "leaf"
        self.len_c = 0
        self.c = []
    def __str__(self):
        return f"node {self.id}: parent = {self.p}, depth = {self.depth}, {self.type}, {self.c}"
n = int(eval(input()))
li = [Tree() for _ in range(n)]
for _ in range(n):
    id, k, *c = list(map(int, readline().split()))
    if k == 0:
        c = []
    else:
        li[id].type = "internal node"
    li[id].id = id
    li[id].c = c
    for j in c:
        li[j].p = id
root = 0
while True:
    a = li[root].p
    if a == -1:
        li[root].type = "root"
        li[root].depth = 0
        break
    root = a
dp = [(root, 0)]
while dp:
    id, d = dp.pop()
    for i in li[id].c:
        li[i].depth = d + 1
        dp.append((i, d + 1))
for i in range(n):
    print((li[i]))
# Original solution
import sys
readline = sys.stdin.readline
class Tree:
    def __init__(self):
        self.id = 0
        self.p = -1
        self.depth = -1
        self.type = "leaf"
        self.len_c = 0
        self.c = []
    def __str__(self):
        return f"node {self.id}: parent = {self.p}, depth = {self.depth}, {self.type}, {self.c}"
n = int(eval(input()))
li = [Tree() for _ in range(n)]
for _ in range(n):
    id, k, *c = list(map(int, readline().split()))
    if k == 0:
        c = []
    else:
        li[id].type = "internal node"
    li[id].id = id
    li[id].c = c
    for j in c:
        li[j].p = id
root = 0
while True:
    a = li[root].p
    if a == -1:
        li[root].type = "root"
        li[root].depth = 0
        break
    root = a
dp = [(root, 0)]
while dp:
    id, d = dp.pop()
    for i in li[id].c:
        li[i].depth = d + 1
        dp.append((i, d + 1))
for i in range(n):
    print((li[i]))



# Optimized solution
import sys
readline = sys.stdin.readline
class Tree:
    __slots__ = ['id', 'p', 'depth', 'type', 'len_c', 'c']
    def __init__(self):
        self.id = 0
        self.p = -1
        self.depth = -1
        self.type = "leaf"
        self.len_c = 0
        self.c = []
    def __str__(self):
        return f"node {self.id}: parent = {self.p}, depth = {self.depth}, {self.type}, {self.c}"
n = int(eval(input()))
li = [Tree() for _ in range(n)]
for _ in range(n):
    id, k, *c = list(map(int, readline().split()))
    if k == 0:
        c = []
    else:
        li[id].type = "internal node"
    li[id].id = id
    li[id].c = c
    for j in c:
        li[j].p = id
root = 0
while True:
    a = li[root].p
    if a == -1:
        li[root].type = "root"
        li[root].depth = 0
        break
    root = a
dp = [(root, 0)]
while dp:
    id, d = dp.pop()
    for i in li[id].c:
        li[i].depth = d + 1
        dp.append((i, d + 1))
for i in range(n):
    print((li[i]))
# Original solution
import sys
readline = sys.stdin.readline
class Tree:
    __slots__ = ['id', 'p', 'depth', 'type', 'c']
    def __init__(self):
        self.id = 0
        self.p = -1
        self.depth = -1
        self.type = "leaf"
        self.c = []
    def __str__(self):
        return f"node {self.id}: parent = {self.p}, depth = {self.depth}, {self.type}, {self.c}"
n = int(input())
li = [Tree() for _ in range(n)]
for _ in range(n):
    id, k, *c = map(int, readline().split())
    if k == 0:
        c = []
    else:
        li[id].type = "internal node"
    li[id].id = id
    li[id].c = c
    for j in c:
        li[j].p = id
root = 0
while True:
    a = li[root].p
    if a == -1:
        li[root].type = "root"
        li[root].depth = 0
        break
    root = a
dp = [(root, 0)]
while dp:
    id, d = dp.pop()
    d += 1
    for i in li[id].c:
        li[i].depth = d
        dp.append((i, d))
print(*li, sep="\n")



# Optimized solution
import sys
readline = sys.stdin.readline
class Tree:
    __slots__ = ['id', 'p', 'depth', 'type', 'c']
    def __init__(self):
        self.id = 0
        self.p = -1
        self.depth = -1
        self.type = "leaf"
        self.c = []
    def __str__(self):
        return f"node {self.id}: parent = {self.p}, depth = {self.depth}, {self.type}, {self.c}"
n = int(input())
li = tuple(Tree() for _ in range(n))
for _ in range(n):
    id, k, *c = map(int, readline().split())
    if k == 0:
        c = []
    else:
        li[id].type = "internal node"
    li[id].id = id
    li[id].c = c
    for j in c:
        li[j].p = id
root = 0
while True:
    a = li[root].p
    if a == -1:
        li[root].type = "root"
        li[root].depth = 0
        break
    root = a
dp = [(root, 0)]
while dp:
    id, d = dp.pop()
    d += 1
    for i in li[id].c:
        li[i].depth = d
        dp.append((i, d))
print(*li, sep="\n")
# Original solution
class Tree:
    nodes = []
    def __init__(self, root = None):
        self.root = root
    def insert(self, label, children = []):
        self.nodes.append(Node(label, children))
    def search_label(self, label):
        for i in self.nodes:
            if i.label == label:
                return i
    def find_parent(self):
        for i in self.nodes:
            if i.children != []:
                for k in i.children:
                    self.search_label(k).parent = i.label
    def distribute_type(self):
        for i in self.nodes:
            if i.parent != -1:
                if i.children == []:
                    i.type_ = "leaf"
                else:
                    i.type_ = "internal node"
    def distribute_depth(self, node):
        if node.children == []:
            return
        for i in node.children:
            x = self.search_label(i)
            x.depth += node.depth + 1
            self.distribute_depth(x)

class Node:
# type_は0:root, 1:internal node, 2:leaf
    def __init__(self, label, children = []):
        self.label = label
        self.type_ = "root"
        self.depth = 0
        self.parent = -1
        self.children = children


tree = Tree()
n = int(eval(input()))
for i in range(n):
    a = list(map(int, input().split()))
    label = a[0]
    if a[1] > 0:
        children = a[2:]
        tree.insert(label, children)
    else:
        tree.insert(label)
tree.find_parent()
tree.distribute_type()
tree.nodes.sort(key = lambda x: x.label)
for i in tree.nodes:
    if i.type_ == "root":
        tree.distribute_depth(i)
for i in tree.nodes:
    print(("node {0:}: parent = {1:}, depth = {2:}, {3:}, {4:}".format(i.label, i.parent, i.depth, i.type_, i.children)))


# Optimized solution
class Tree:
    nodes = []
    def __init__(self, root = None):
        None
    def insert(self, label, children = []):
        if children != []:
            for i in children:
                self.nodes[label].children.append(self.nodes[i])
                self.nodes[i].parent = self.nodes[label]
                self.nodes[i].type_ = "internal node"
    def depth(self, node):
        if node.children == []:
            node.type_ = "leaf"
        else:
            for i in node.children:
                i.depth = node.depth + 1
                self.depth(i)

class Node:
    def __init__(self, label, children = []):
        self.label = label
        self.type_ = "root"
        self.depth = 0
        self.parent = -1
        self.children = [] # self.children = childrenにするとハマる

tree = Tree()
n = int(input())
for i in range(n):
    tree.nodes.append(Node(i))
for i in range(n):
    children = []
    label, num, *children = map(int, input().split())
    tree.insert(label, children)
for i in tree.nodes:
    if i.parent == -1:
        tree.depth(i)
        None
if n == 1:
    tree.nodes[0].type_ = "root"
for i in tree.nodes:
    print("node {0:}: parent = {1:}, depth = {2:}, {3:}, ".\
            format(i.label, i.parent if i.parent == -1 else i.parent.label,\
            i.depth, i.type_), end = "")
    print([i.label for i in i.children])
# Original solution
class Node:
    def __init__(self):
        self.p = None
        self.depth = None
        self.l = None
        self.r = None

    def show(self, i):
        global T
        ans = 'node {}: parent = {}, depth = {}, {}, {}'.format(i, self.p, self.depth, self.t(), self.degree(T))
        print(ans)

    def degree(self, T):
        if self.l != None:
            deg = [self.l]
            ch = T[self.l]
            while ch.r != None:
                deg.append(ch.r)
                ch = T[ch.r]
            return deg
        else:
            return []

    def t(self):
        if self.p == -1:
            return 'root'
        elif self.l == None:
            return 'leaf'
        else:
            return 'internal node'

def set_depth(root, d):
    r = T[root]
    r.depth = d
    if r.r != None:
        set_depth(r.r, d)
    if r.l != None:
        set_depth(r.l, d+1)

n = int(eval(input()))

T = [Node() for x in range(n)]
for i in range(n):
    A = list(map(int, input().split()))
    l = 0
    for x in range(A[1]):
        if x == 0:
            T[A[0]].l = A[2:][x]
        else:
            T[l].r = A[2:][x]
        l = A[2:][x]
        T[A[2:][x]].p = A[0]

root = None
for i in range(n):
    if T[i].p == None:
        root = i
        T[root].p = -1

set_depth(root, 0)

count = 0
for node in T:
    node.show(count)
    count += 1

# Optimized solution
def set_info(i, p, d):
    r = T[i]
    r[1], r[2] = p, d
    for c in r[0]:
        set_info(c, i, d+1)

n = int(eval(input()))
T = [None] * n
root = set(range(n))

for i in range(n):
    A = list(map(int, input().split()))
    ch = A[2:]
    T[A[0]] = [ch, None, None]
    root -= set(ch)

set_info(root.pop(), -1, 0)

for i,node in enumerate(T):
    ch, p, d = node
    print(('node {}: parent = {}, depth = {}, {}, {}'.format(
            i, p, d, 'root' if not d else 'internal node' if ch else 'leaf', ch
        )))
# Original solution
def set_pdt(i, p, d):
    u = tree[i]
    u[0], u[1] = p, d
    for c in u[3]:
        set_pdt(c, i, d+1)
    else:
        if u[0] == -1:
            u[2] = "root"
        elif u[3]:
            u[2] = "internal node"
        else:
            u[2] = "leaf"

n = int(eval(input()))
#         p d t ch
tree = [[-1,0,0,0] for _ in range(n)]
root = set(range(n))

for _ in range(n):
    i, k, *c = list(map(int, input().split()))
    tree[i][3] = c
    root -= set(c)
    
for u in root:
    set_pdt(u, -1, 0)

for i in range(n):
    u = tree[i]
    print(("node {}: parent = {}, depth = {}, {}, {}".format(i, *u)))

# Optimized solution
def set_pdt(i, p, d):
    u = tree[i]
    u[0], u[1] = p, d
    for c in u[3]:
        set_pdt(c, i, d+1)
    else:
        if u[0] == -1:
            u[2] = "root"
        elif u[3]:
            u[2] = "internal node"
        else:
            u[2] = "leaf"

n = int(eval(input()))
tree = [[-1,0,0,0] for _ in range(n)]
root = set(range(n))

for _ in range(n):
    i, k, *c = list(map(int, input().split()))
    tree[i][3] = c
    root -= set(c)
    
set_pdt(root.pop(), -1, 0)

for i in range(n):
    u = tree[i]
    print(("node {}: parent = {}, depth = {}, {}, {}".format(i, *u)))
# Original solution
n = int(eval(input()))
nodes = []
id_list = []
output = [None for i in range(n)]
cnt = 0
root = set(range(n))
for i in range(n):
    id, _, *li = list(map(int, input().split(' ')))
    root -= set(li)
    nodes.append(li)
    id_list.append(id)

def rooted_tree(id, depth, parent):
    out = {}
    ind = id_list.index(id)
    out['node'] = id
    out['parent'] = parent
    out['depth'] = depth
    out['c'] = nodes[ind]
    if depth == 0:
        out['type'] = 'root'
    elif len(nodes[ind]) == 0:
        out['type'] = 'leaf'
    else:
        out['type'] = 'internal node'
    output[id] = out
    for i in (nodes[ind]):
        rooted_tree(i, depth+1, id)

rooted_tree(root.pop(), 0, -1)
for line in output:
    print(("node {}: parent = {}, depth = {}, {}, {}".format(line['node'], line['parent'], line['depth'], line['type'], line['c'])))



# Optimized solution
n = int(eval(input()))
nodes = [0 for i in range(n)]
output = [None for i in range(n)]
cnt = 0
root = set(range(n))
for i in range(n):
    id, _, *li = list(map(int, input().split(' ')))
    root -= set(li)
    nodes[id] = li

def rooted_tree(id, depth, parent):
    out = {}
    out['node'] = id
    out['parent'] = parent
    out['depth'] = depth
    out['c'] = nodes[id]
    if depth == 0:
        out['type'] = 'root'
    elif len(nodes[id]) == 0:
        out['type'] = 'leaf'
    else:
        out['type'] = 'internal node'
    output[id] = out
    for i in (nodes[id]):
        rooted_tree(i, depth+1, id)

rooted_tree(root.pop(), 0, -1)
for line in output:
    print(("node {}: parent = {}, depth = {}, {}, {}".format(line['node'], line['parent'], line['depth'], line['type'], line['c'])))
# Original solution
#coding:utf-8
#1_7_A
class Node():
    def __init__(self, node_id, degree, children):
        self.node_id    =   node_id
        self.parent     =   -1
        self.depth      =   0
        self.typ        =   "leaf"
        self.degree     =   degree
        self.children   =   children

    def set_attr(self, parent, depth):
        self.parent =   parent
        self.depth  =   depth
        for child_id in self.children:
            self.typ = "internal node"
            tree[child_id].set_attr(self.node_id, self.depth + 1)
        if self.parent == -1:
            self.typ = "root"

n = int(eval(input()))
tree = [None for i in range(n)]
root = set(range(n))

for i in range(n):
    info = list(map(int, input().split()))
    tree[info[0]] = Node(info[0], info[1], info[2:])
    root -= set(info[2:])

root_id = root.pop()
tree[root_id].set_attr(-1, 0)

for node in tree:
    print(("node {}: parent = {}, depth = {}, {}, {}".format(node.node_id, node.parent, node.depth, node.typ, node.children)))

# Optimized solution
#coding:utf-8
#1_7_A
class Node():
    def __init__(self, node_id, children):
        self.node_id    =   node_id
        self.parent     =   -1
        self.depth      =   0
        self.typ        =   "leaf"
        self.children   =   children

    def set_attr(self, parent, depth):
        self.parent =   parent
        self.depth  =   depth
        for child_id in self.children:
            self.typ = "internal node"
            tree[child_id].set_attr(self.node_id, self.depth + 1)
        if self.parent == -1:
            self.typ = "root"

n = int(eval(input()))
tree = [None for i in range(n)]
root = set(range(n))

for i in range(n):
    info = list(map(int, input().split()))
    tree[info[0]] = Node(info[0], info[2:])
    root -= set(info[2:])

root_id = root.pop()
tree[root_id].set_attr(-1, 0)

for node in tree:
    print(("node {}: parent = {}, depth = {}, {}, {}".format(node.node_id, node.parent, node.depth, node.typ, node.children)))
# Original solution
# -*- coding:utf-8 -*-
import sys
from collections import OrderedDict


def cleate_node_dict(children):
    node_dict = OrderedDict()
    for val in children:
        node_dict[val] = OrderedDict()
    return node_dict


def cleate_tree(nodes):
    tree = nodes.copy()
    for node, children in list(nodes.items()):
        for key in list(children.keys()):
            children[key] = nodes[key]
            del tree[key]

    return tree


def rec(current, acc, parent=-1, depth=0):
    if current == {}:
        return
    for node, children in list(current.items()):
        cld_lst = list(children.keys())
        acc[node] = "node {0}: parent = {1}, depth = {2}, {3}, {4}".format(
                node, parent, depth, node_type(parent, children), cld_lst)
        rec(children, acc, node, depth+1)


def node_type(parent, children):
    if parent == -1:
        return "root"
    elif children != {}:
        return "internal node"
    else:
        return "leaf"


if __name__ == "__main__":
    n = int(eval(input()))
    lst = [[int(n) for n in val.split()] for val in sys.stdin.readlines()]
    nodes = {val[0]: cleate_node_dict(val[2:]) for val in lst}
    tree = cleate_tree(nodes)
    node_info = {}
    rec(tree, node_info)
    for key, val in sorted(node_info.items()):
        print(val)

# Optimized solution
# -*- coding:utf-8 -*-
import sys
from collections import OrderedDict


def cleate_node_dict(children):
    node_dict = OrderedDict()
    for val in children:
        node_dict[val] = None
    return node_dict


def cleate_tree(nodes):
    tree = nodes.copy()
    for node, children in list(nodes.items()):
        for key in list(children.keys()):
            children[key] = nodes[key]
            del tree[key]

    return tree


def rec(current, acc, parent=-1, depth=0):
    if current == {}:
        return
    for node, children in list(current.items()):
        cld_lst = list(children.keys())
        acc[node] = "node {0}: parent = {1}, depth = {2}, {3}, {4}".format(
                node, parent, depth, node_type(parent, children), cld_lst)
        rec(children, acc, node, depth+1)


def node_type(parent, children):
    if parent == -1:
        return "root"
    elif children != {}:
        return "internal node"
    else:
        return "leaf"


def rooted_trees(lst, n):
    nodes = {val[0]: cleate_node_dict(val[2:]) for val in lst}
    tree = cleate_tree(nodes)
    node_info = [None] * n
    rec(tree, node_info)
    print(("\n".join(node_info)))


if __name__ == "__main__":
    n = int(eval(input()))
    lst = [[int(n) for n in val.split()] for val in sys.stdin.readlines()]
    rooted_trees(lst, n)
# Original solution
a,b,c = list(map(int, input().split()))
if a == max(a,b,c):
    print((int(b*c / 2)))
elif b == max(a,b,c):
    print((int(a*c / 2)))
elif c == max(a,b,c):
    print((int(a*b / 2)))


# Optimized solution
a, b, c = list(map(int, input().split()))
print((a*b // 2))
# Original solution
a,b,c = sorted([int(i) for i in input().split()])
print((int(a*b/2)))

# Optimized solution
a = [int(i) for i in input().split()]
a = sorted(a)
ans = int(a[0] * a[1]/2)
print(ans)
# Original solution
a,b,c = list(map(int,input().split()))
if a**2+b**2==c**2:
    ans = a*b//2
elif a**2+c**2==b**2:
    ans = a*c//2
else:
    ans = b*c//2
print(ans)

# Optimized solution
a,b,c = list(map(int,input().split()))
print((a*b//2))
# Original solution
a,b,c = list(map(int,input().split()))
print((a*b//2))

# Optimized solution
a,b,c = sorted(map(int,input().split()))
print((a*b//2))
# Original solution
print(((lambda l:l[0]*l[1]//2)(sorted(list(map(int,input().split()))))))

# Optimized solution
print(((lambda l:l[0]*l[1]//2)(list(map(int,input().split())))))
# Original solution
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians
from itertools import permutations, combinations, product
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits

def input(): return sys.stdin.readline().strip()
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(): return list(map(int, input().split()))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
MOD = 10 ** 9 + 7

AB, BC, CA = [int(x.strip("|")) for x in input().split()]
print((int(AB*BC/2)))


# Optimized solution
えーびー,びーしー,_ = list(map(int,input().split()))
めんせき =えーびー*びーしー//2
print(めんせき)
# Original solution
X = list(map(int,input().split()))
X.sort()
print((X[0]*X[1]//2))


# Optimized solution
AB,BC,CA = list(map(int,input().split()))
print((AB*BC//2))
# Original solution
def main():
    a, b, c = (int(i) for i in input().split())
    from math import sqrt
    s = (a + b + c) / 2
    print((int(sqrt(s*(s-a)*(s-b)*(s-c)))))


if __name__ == '__main__':
    main()


# Optimized solution
def main():
    a, b, c = (int(i) for i in input().split())
    print((a*b//2))


if __name__ == '__main__':
    main()
# Original solution
# -*- coding: utf-8 -*-

a, b, c = list(map(int, input().split()))
print((int(a*b/2)))


# Optimized solution
A, B, C = list(map(int, input().split()))
print(((A * B) // 2))
# Original solution
a = list(map(int,input().split()))
a.sort()
print((int(a[0]*a[1]/2)))

# Optimized solution
l = list(map(int,input().split()))
l.sort()
print((int(l[0]*l[1]/2)))
# Original solution
# coding: utf-8
from sys import stdin
AB,BC,AC = list(map(int, stdin.readline().rstrip().split()))
print((int(AB*BC/2)))

# Optimized solution
# coding: utf-8
AB,BC,AC = list(map(int, input().split()))
print((AB*BC//2))
# Original solution
AB, BC, CA = list(map(int, input().split()))
print((AB * BC//2))

# Optimized solution
A, B, C = list(map(int, input().split()))
print((A * B // 2))
# Original solution
A, B, C =list(map(int,input().split()))
print(((A*B)//2))

# Optimized solution
a,b,c = list(map(int,input().split()))
print((int((1/2)*a*b)))
# Original solution
a,b,c = list(map(int,input().split()))
print((int(a*b/2)))

# Optimized solution
a,b,c = list(map(int,input().split()))
print((a*b//2))
# Original solution
a,b,c = list(map(int,input().split()))
print(((a*b)//2))

# Optimized solution
L = sorted(list(map(int,input().split())))
print(((L[0]*L[1])//2))
# Original solution
import itertools
import math
import fractions
import functools
import copy
ab, bc, ca = list(map(int, input().split()))

print((ab*bc//2))

# Optimized solution
def main():
    # n = int(input())
    a, b, c = list(map(int, input().split()))
    # h = list(map(int, input().split()))
    # s = input()
    print((a*b//2))



if __name__ == '__main__':
    main()
# Original solution
AB,BC,CA = list(map(int,input().split()))
print((AB*BC//2))

# Optimized solution
a,b,c=list(map(int,input().split()))
print((a*b//2))
# Original solution
a, b, c = list(map(int, input().split()))
print((int(a*b/2)))

# Optimized solution
a, b, c = list(map(int, input().split()))
ans = a * b // 2
print(ans)
# Original solution
a,b,c = list(map(int, input().split()))
print((a*b//2))

# Optimized solution
AB,BC,CA = list(map(int,input().split()))

print((AB*BC//2))
# Original solution
a,b,c=list(map(int,input().split()))
s=int((a*b)/2)
print(s)

# Optimized solution
a,b,c=list(map(int,input().split()))
print((int(a*b/2)))
# Original solution
A, B, C = sorted(map(int,input().split()))
print((int((A*B)/2)))

# Optimized solution
A, B, C = list(map(int,input().split()))
print((A*B//2))
# Original solution
a, b, c = list(map(int,input().split()))
print(((a*b)//2))

# Optimized solution
def ans():
  A, B, C = list(map(int,input().split()))
  print(((A*B)//2))
ans()
# Original solution
import math
V = [int(n) for n in input().split()]
s = sum(V) / 2
A = math.sqrt(s*(s-V[0])*(s-V[1])*(s-V[2]))
print((int(A)))

# Optimized solution
a, b, c = list(map(int, input().split()))
print((a * b // 2))
# Original solution
a = list(map(int,input().split()))
a.sort()
print((a[0]*a[1]//2))

# Optimized solution
R= list(map(int,input().split()))
R.sort()
print((R[0] * R[1] // 2))
# Original solution
a, b, c = list(map(int, input().split()))
print((int(a * b * 0.5)))

# Optimized solution
a, b, c = list(map(int, input().split()))
print((a * b // 2))
# Original solution
ab,bc,ca=input().split()
ab,bc,ca=int(ab),int(bc),int(ca)

print((ab*bc//2))


# Optimized solution
a,b,_=list(map(int,input().split()))
print((a*b//2))
# Original solution
import math
a,b,c=sorted(map(int,input().split()))
print((math.floor(a*b/2)))

# Optimized solution
x, y, z = sorted(map(int, input().split()))
print(((x * y) // 2))