Pavel loves grid mazes. A grid maze is an *n* × *m* rectangle maze where each cell is either empty, or is a wall. You can go from one cell to another only if both cells are empty and have a common side.

Pavel drew a grid maze with all empty cells forming a connected area. That is, you can go from any empty cell to any other one. Pavel doesn't like it when his maze has too little walls. He wants to turn exactly *k* empty cells into walls so that all the remaining cells still formed a connected area. Help him.
The first line contains three integers *n*, *m*, *k* (1 ≤ *n*, *m* ≤ 500, 0 ≤ *k* &lt; *s*), where *n* and *m* are the maze's height and width, correspondingly, *k* is the number of walls Pavel wants to add and letter *s* represents the number of empty cells in the original maze.

Each of the next *n* lines contains *m* characters. They describe the original maze. If a character on a line equals ".", then the corresponding cell is empty and if the character equals "#", then the cell is a wall.
# https://codeforces.com/problemset/problem/377/A

from collections import defaultdict as ddict
from collections import deque



class Null():  # another None class
    def __new__(cls):
        return cls.null
    def __reduce__(self):
        return (Null, ())
    def __bool__(self):
        return False
    def __repr__(self):
        return "null"
null = Null.null = object.__new__(Null)


class Nodes(dict):
    "Doesn't support nodes deletion. It's memory expensive or time-expensive"
    pseudo_id = 0
    
    def __init__(self, name, parent, node_weight):
        # self contains: key -> `Nodes`, value -> Edge weight to that nodeNode
        super().__init__()
        
        self._name = name
        self._weight = node_weight
        self._parent = parent
        self.cache = None

        self._id = Nodes.pseudo_id
        Nodes.pseudo_id += 1

    @property
    def name(self):
        return self._name

    @property
    def neighbors(self):
        return tuple(super().keys())

    @property
    def neighbor_names(self):
        # Remember that super() or self[] is a dict whose keys are a
        # `Nodes` data type
        return tuple(self_.name for self_ in self)

    @property
    def neighbor_repr(self):
        # Remember that super() or self[] is a dict whose keys are a
        # `Nodes` data type, and values are edge's weight
        return tuple(f"{item}-{key.name!r}" for key, item  in self.items())

    def has_edge_to(self, target_node):
        if not isinstance(target_node, Nodes):
            target_node = self._parent[target_node]
        
        return target_node in self
        
    def remove_edge(self, target_node, not_found_error=True):
        """
        Remove an edge from self to others for directional, or Both direction for
        undirecional. might be error when not found.
        """
        if not isinstance(target_node, Nodes):
            target_node = self._parent[target_node]
        if not self.has_edge_to(target_node):
            if not_found_error:
                raise ValueError("Target node is not found")
        else:
            del self[target_node]
            if not self._parent.directional:
                target_node.remove_edge(self, not_found_error=False)
                
    def add_edge(self, target_node, edge_weight=null):
        "Add edge from self to others for directional, or both for undirectional"
        
        if edge_weight is null:
            edge_weight = self._parent.default_edge_w
            
        if not isinstance(target_node, Nodes):
            target_node = self._parent[target_node]
        self[target_node] = edge_weight

        if not self._parent.directional:
            target_node[self] = edge_weight

    def __hash__(self):
        return hash(self._name)

    def __eq__(self, other):
        return id(self) == id(other) or (hasattr(other, "_id") and
                                         self._id == other._id)
    def __str__(self):
        _1, _2 = self._id, self._name
        return f"<{_1:02d}-{_2}:{self._weight}>"

    def __repr__(self):
        _1, _2 = self._id, self._name
        _3 = ', '.join(self.neighbor_repr)
        return f"<{_1:02d}-{_2}:{self._weight}> : {_3}"

    
    

class Graph():
    "Doesn't support nodes deletion. It's memory expensive or time-expensive"
    def __init__(self, directional=False, def_edge_weight=1, def_node_weight=0,
                 roots=[]):
        self.default_edge_w = def_edge_weight  # default edge weight
        self.default_node_w = def_node_weight  # default value held by nodes
        self.directional = directional  # directional graph
        self.roots = roots  # the roots for the graph. Is mostly useless tho

        # contains key: name/str, value: `Nodes`
        self._nodes = {}
        self._names = {}  # store Nodes as its keys, and string:name as its value

    def add_node(self, name, weight=null):
        # basically node's name could be anything that hashable and have __eq__
        # except `Nodes` itself. It's best to just use immutables only.
        assert not isinstance(name, Nodes)
        if weight is null:
            weight = self.default_node_w
        temp = Nodes(name, self, weight)
        self._nodes[name] = temp
        self._names[temp] = name
        self.repr_space = 0
        return temp

    def add_nodes(self, iterable_of_tuples):
        # format iterable_of_tuples: [('name1', weight1), ('name2', weight2), etc]
        # just like its `.add_node()` parameter
        for parameters in iterable_of_tuples:
            self.add_node(*parameters)

    def add_edge(self, from_edge, to_edge):
        self._nodes[from_edge].add_edge(to_edge)

    def add_edges(self, iterable_of_edge_pairs):
        for from_edge, to_edge in iterable_of_edge_pairs:
            self._nodes[from_edge].add_edge(to_edge)

    def delete_node(self, target_node):
        raise NotImplementedError()

    def has_node(self, node:Nodes):
        return node in self

    def __contains__(self, other):
        if not isinstance(other, Nodes):
            return other in self._nodes
        elif isinstance(other, Nodes):
            return other in self._names  # get names by object
        
    def __getitem__(self, node_name):
        return self._nodes[node_name]

    # an easier way to call self.add_node
    def __setitem__(self, node_name, value):
        if value is null:
            value = self.default_node_w
        self.add_node(node_name, value)

    def __repr__(self):
        ret = []
        for node_name in self._nodes:
            _ = ", ".join(self._nodes[node_name].neighbor_repr)
            
            ret.append(
                f"{node_name!s:<{self.repr_space}} :  {_}"
                )
        return "\n".join(ret)

    def __iter__(self):
        return iter(self._nodes.values())

    def __len__(self):
        return len(self._nodes)
    
    def iterate_names(self):
        return self._nodes.keys()

    def iterate_BFS(self, node_enter_point):
        # breadth first search
        if not isinstance(node_enter_point, Nodes):
            node_enter_point = self._nodes[node_enter_point]
        
        added = {node_enter_point}  # set of nodes that have been added/iterated
        queue = deque()             # (depth_from_pivot, current_iterated_node)
        queue.append((0, node_enter_point))
        while queue:
            curr_depth, curr_item = tuple_ = queue.popleft()
            yield tuple_
            next_depth = curr_depth + 1
            for i in curr_item:
                if i not in added:
                    queue.append((next_depth, i))
                    added.add(i)


    def iterate_DFS(self, node_enter_point):
        # depth first search
        if not isinstance(node_enter_point, Nodes):
            node_enter_point = self._nodes[node_enter_point]

        # (depth_from_pivot, current_iterated_node)
        queue = deque()  # we will use it as stack data structure
        added = {node_enter_point}  # set of nodes that have been added/iterated
        queue.append((0, node_enter_point))
        while queue:
            curr_depth, curr_item = tuple_ = queue.pop()
            yield tuple_
            next_depth = curr_depth + 1
            for i in curr_item:
                if i not in added:
                    queue.append((next_depth, i))
                    added.add(i)
    


def map_graph_generate(string_map, *param):
    "Give a graph with cartesian-like connection according to string_map"
    # Graph's nodes naming convention: (Y pos, X pos), 0 indexed
    global ret
    
    
    if isinstance(string_map, str):
        list_of_str_map = string_map.split("\n")
    else:
        list_of_str_map = string_map

    ret = Graph(directional=False, *param)
    lrow = len(list_of_str_map)
    lcol = len(list_of_str_map[0])
    
    for row_ind, row in enumerate(list_of_str_map):
        for col_ind, char in enumerate(row):
            if list_of_str_map[row_ind][col_ind] == ".":
                temp = ret.add_node((row_ind, col_ind))

                if 0 <= row_ind-1:
                    if (list_of_str_map[row_ind-1][col_ind] == "."):
                        ret[(row_ind-1, col_ind)].add_edge(temp)
                    
                if 0 <= col_ind-1:
                    if (list_of_str_map[row_ind][col_ind-1] == "."):
                        ret[(row_ind, col_ind-1)].add_edge(temp)

    x_edge_index = (0, lcol-1)
    y_edge_index = (0, lrow-1)
    roots = [i for i in ret.iterate_names() if (i[1] in x_edge_index or
                                                i[0] in y_edge_index
                                                # remember: (y, x) format
                                                )]
    ret.roots = roots
    
    return ret







r, c, number = map(int, input().split())

map_ = []
for i in range(r):
    map_.append(input())


graph = map_graph_generate(map_)
map_ = list(map(list, map_))


while number > 0:
    if any(len(i) == 1 for i in graph):
        for i in graph:
            if len(i) == 0:
                del graph._nodes[i.name]
            elif len(i) == 1:
                map_[i.name[0]][i.name[1]] = "X"
                for j in i.neighbors:
                    i.remove_edge(j)
                number -= 1
                if number <= 0:
                    break
map_ = list(map(lambda x: "".join(x), map_))
print("\n".join(map_))




    
