size = input()
size = int(size)
b = []
def merge_in_b (a , b): #用来将新输入的索引和数字输入到汇总的列表中
    b_1 = b
    b_size_1 = len(b_1)
    if b_size_1 == 0:
        b_1.append(int(a[0]))
        b_1.append(int(a[1]))
        return b_1
    flag = 0
    k = 0
    for j in range(int(b_size_1/2)):
        if(int(a[0]) == b_1[k]):
            b_1[k+1] += int(a[1]) #b[0]存储第一个索引,b[1]存储第一个索引对应的数,以此类推
            flag = 1
            break
        k = k + 2 #每次跳过存储数据的部分
    if(flag == 0):
        b_1.append(int(a[0]))
        b_1.append(int(a[1]))
                  
                   
    return b_1


for i in range(size):
    a = input()
    a = a.split()#以空格将a隔开,得到的是列表形式
    b = merge_in_b (a , b)
b_size_2 = len(b)
c = {} #最后以字典的形式存储合并后的列表(为了排序)
k = 0
for i in range(int(b_size_2/2)):
    c[b[k]] = b[k+1]
    k = k + 2
d = sorted(c.items(),key=lambda x:x[0])#sorted(c.items(),key =lambda x:x[0])得到以key排序后的二元组形式列表
len_d = len(d)

for i in range(len_d):
    print(d[i][0],d[i][1])#二元组的第一个值是索引,第二个是对应的值

PS:本题最重要的是存储合并后的索引和值对的形式,形式不同,算法不同