Misha hacked the Codeforces site. Then he decided to let all the users change their handles. A user can now change his handle any number of times. But each new handle must not be equal to any handle that is already used or that was used at some point.

Misha has a list of handle change requests. After completing the requests he wants to understand the relation between the original and the new handles of the users. Help him to do that.
The first line contains integer *q* (1 ≤ *q* ≤ 1000), the number of handle change requests.

Next *q* lines contain the descriptions of the requests, one per line.

Each query consists of two non-empty strings *old* and *new*, separated by a space. The strings consist of lowercase and uppercase Latin letters and digits. Strings *old* and *new* are distinct. The lengths of the strings do not exceed 20.

The requests are given chronologically. In other words, by the moment of a query there is a single person with handle *old*, and handle *new* is not used and has not been used by anyone.
import collections
import sys

input = sys.stdin.readline
inf = 1_000_000_000 + 7
mod = inf


def find(a: list[int], q: int) -> bool:
    i = find_lower(a, q)
    return i >= 0 and a[i] == q


def binary_search(a: list[int], x: int) -> int:
    """find i: a[i] = x. Else -1"""
    i = find_lower(a, x)
    return i if (i >= 0 and a[i] == x) else -1


def find_lower(a: list[int], x: int) -> int:
    """max i: a[i] <= x"""
    l = -1  # a[l] <= x
    r = len(a)  # a[r] > x
    while r > l + 1:
        m = (l + r) // 2
        if a[m] <= x:
            l = m
        else:
            r = m

    return l


def find_upper(a: list[int], x: int) -> int:
    """min i: a[i] >= x"""
    l = -1
    r = len(a)
    while l + 1 < r:
        m = (l + r) // 2
        if a[m] >= x:
            r = m
        else:
            l = m

    return r


def linear_search(a: list[int], x: int) -> int:
    for i, num in enumerate(a):
        if num == x:
            return i

    return -1


def rec_dfs(graph: list[list[int]]) -> None:
    n = len(graph)
    visited = [False] * n

    def dfs(u: int) -> None:
        visited[u] = True
        for v in graph[u]:
            if not visited[v]:
                dfs(v)

    for i in range(1, n + 1):
        if not visited[i]:
            dfs(i)


def iter_dfs(graph: list[list[int]]) -> None:
    n = len(graph)
    visited = [False] * n

    def dfs(v: int) -> None:
        q = collections.deque()
        q.append(v)
        while q:
            u = q.popleft()
            if not visited[u]:
                for x in graph[u]:
                    q.append(x)

    for i in range(1, n + 1):
        if not visited[i]:
            dfs(i)


def bfs(graph: list[list[int]], source: int, dest: int) -> int:
    global inf
    d = [inf] * len(graph)
    d[source] = 0
    q = collections.deque()
    q.append(source)
    while q:
        u = q.popleft()
        for v in graph[u]:
            if d[v] == inf:
                d[v] = 1 + d[u]
                q.append(v)

    return d[dest]


def quick_pow(x: int, n: int) -> float:
    if n < 0:
        return 1 / quick_pow(x, -n)
    if n == 0:
        return 1
    if n % 2 == 0:
        return quick_pow(x, n // 2) * quick_pow(x, n // 2)
    return x * quick_pow(x, n - 1)


def gcd(a: int, b: int) -> int:
    if a > 0:
        return gcd(b % a, a)
    return b


def sieve(n: int) -> list[bool]:
    prime = [True for _ in range(n + 1)]
    p = 2
    while p * p <= n:
        if prime[p]:
            for i in range(p * p, n + 1, p):
                prime[i] = False
        p += 1

    return prime


class SegmentTree:
    # TODO: complete tree ^^
    size: int
    tree: list[int]

    def __init__(self, n: int, a: list[int]) -> None:
        self.size = 1
        while self.size < n:
            self.size *= 2

        self.tree = [0] * (2 * self.size - 1)
        # self.build(a, )


def print_matrix(matrix: dict[list[int]]) -> None:
    for row in matrix.values():
        sys.stdout.write(" ".join(str(x) for x in row))
        sys.stdout.write("\n")


def print_answer(flag: bool) -> None:
    sys.stdout.write("YES\n") if flag else sys.stdout.write("NO\n")


def print_list(array: list[int]) -> None:
    sys.stdout.write(" ".join(str(x) for x in array))
    sys.stdout.write("\n")


def print_int(x: int) -> None:
    sys.stdout.write(f"{x}\n")


def read_int() -> int:
    return int(input().strip())


def read_tuple() -> (int, int):
    return map(int, input().split())


def read_tuple_strings() -> (str, str):
    return input().split()


def read_list() -> list[int]:
    return list(map(int, input().split()))


class DSU:
    def __init__(self, n: int) -> None:
        self.cc = n
        self.rank = [1] * (n + 1)
        self.parent = [i for i in range(n + 1)]

    # def make_set(self, x: int):
    #     self.parent[x] = x
    #     self.rank[x] = 1

    def find(self, x: int) -> int:
        if x != self.parent[x]:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x: int, y: int) -> None:
        x = self.find(x)
        y = self.find(y)
        if x != y:
            self.cc -= 1
            if self.rank[x] < self.rank[y]:
                x, y = y, x
            self.parent[y] = x
            diff = self.rank[y]
            self.rank[x] += diff


def solve():
    t = read_int()
    hash_map = dict()
    while t > 0:
        t -= 1
        old, new = input().split()
        if old not in hash_map.keys():
            hash_map[new] = old
        else:
            hash_map[new] = hash_map[old]
            hash_map.pop(old)

    return hash_map


def main():
    hash_map = solve()
    print_int(len(hash_map.keys()))
    for key in hash_map.keys():
        sys.stdout.write(f"{hash_map[key]} {key}\n")


if __name__ == "__main__":
    main()
