fun c91(args: Array<String>) {
    val n = args[0].toInt()
    val aList = args.drop(1).take(n).map { it.split(" ").map { it.toInt() } }
    val bList = args.drop(1).drop(n).take(n).map { it.split(" ").map { it.toInt() } }
    var edgeToCost = mutableMapOf<Pair<Int, Int>, Int>()
    aList.forEachIndexed { aIndex, aElem ->
        edgeToCost.put(Pair(0, aIndex + 1), 1)
        bList.forEachIndexed { bIndex, bElem ->
            if (aElem[0] < bElem[0] && aElem[1] < bElem[1]) {
                edgeToCost.put(Pair(aIndex + 1, bIndex + n + 1), 1)
            }
        }
    }
    bList.forEachIndexed { bIndex, bElem ->
        edgeToCost.put(Pair(bIndex + n + 1, 2 * n + 1), 1)
    }

    val fordFulkerson = FordFulkerson(2 * n + 1, edgeToCost)
    val (maxFlow, graph) = fordFulkerson.execute(0, 2 * n + 1)
    println(maxFlow)
}

class FordFulkerson(size: Int, edgeToFlow: Map<Pair<Int, Int>, Int>) {
    private val size = size
    private val edgeToFlow = edgeToFlow.entries
            .flatMap { listOf(Pair(it.key, it.value), Pair(Pair(it.key.second, it.key.first), 0)) }
            .toMap()

    // Returns MaxFlow and PairToCost
    fun execute(start: Int, end: Int): Pair<Int, Map<Pair<Int, Int>, Int>> {
        var totalFlow = 0
        var localEdgeToFlow = edgeToFlow
        while (true) {
            val bellmanFord = BellmanFord(size, localEdgeToFlow.filter { it.value > 0 })
            val (path, maxFlow) = bellmanFord.getShortestPath(start, end)
            if (maxFlow <= 0) {
                break
            }
            totalFlow += maxFlow

            localEdgeToFlow = localEdgeToFlow
                    .map {
                        val (from, to) = it.key
                        val cost =
                                when {
                                    (0 until path.size - 1).any { from == path[it] && to == path[it + 1] }
                                    -> it.value - maxFlow
                                    (0 until path.size - 1).any { from == path[it + 1] && to == path[it] }
                                    -> it.value + maxFlow
                                    else -> it.value
                                }
                        Pair(Pair(from, to), cost)
                    }
                    .filter { it.second >= 0 }
                    .toMap()
        }
        return Pair(totalFlow, localEdgeToFlow)
    }
}

class BellmanFord(size: Int, edge2Cost: Map<Pair<Int, Int>, Int>) {
    private val size = size
    private val edge2Cost = edge2Cost
    private val from2To2Cost = Array(size + 1) { Array(size + 1) { Int.MAX_VALUE / 2 } }

    init {
        init()
    }

    private fun init() {
        (0..size).forEach { from ->
            (0..size).forEach { to ->
                from2To2Cost[from][to] = Int.MAX_VALUE / 2
            }
        }
        (0..size).forEach {
            from2To2Cost[it][it] = 0
        }
    }

    fun clear() {
        init()
    }

    // This has side-effect
    fun getShortestPath(start: Int, end: Int): Pair<List<Int>, Int> {
        var prevOf = Array(size + 1) { -1 }

        while (true) {
            var updated = false
            edge2Cost.forEach { elem ->
                val (from, to) = elem.key
                val cost = elem.value
                if (from2To2Cost[start][to] > from2To2Cost[start][from] + cost) {
                    from2To2Cost[start][to] = from2To2Cost[start][from] + cost
                    prevOf[to] = from
                    updated = true
                }
            }
            if (!updated) {
                break
            }
        }

        var reversedPath = mutableListOf<Int>()
        var curr = end
        while (curr != -1) {
            reversedPath.add(curr)
            curr = prevOf[curr]
        }

        val path = reversedPath.reversed()
        val maxFlow = (0 until path.size - 1).map { from2To2Cost[path[it]][path[it + 1]] }.min() ?: 0

        return Pair(path, maxFlow)
    }

    // This has side-effect
    fun getCostList(start: Int): List<Int> {
        while (true) {
            var updated = false
            edge2Cost.forEach { elem ->
                val (from, to) = elem.key
                val cost = elem.value
                if (from2To2Cost[start][to] > from2To2Cost[start][from] + cost) {
                    from2To2Cost[start][to] = from2To2Cost[start][from] + cost
                    updated = true
                }
            }
            if (!updated) {
                break
            }
        }
        return from2To2Cost[start].toList()
    }
}

fun main(args: Array<String>) {
    c91(readLineList())
}

fun readLineList(): Array<String> {
    val lineList = mutableListOf<String>()
    while (true) {
        val line = readLine()
        if (line.isNullOrBlank()) {
            break
        } else {
            lineList.add(line!!)
        }
    }
    return lineList.toTypedArray()
}