Решение
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
class DSU(n: Int) {
private val parent = IntArray(n + 1) { it }
private val rank = IntArray(n + 1)
var components = n
fun find(x: Int): Int {
if (parent[x] != x) {
parent[x] = find(parent[x]) // Path compression
}
return parent[x]
}
fun union(x: Int, y: Int) {
val rootX = find(x)
val rootY = find(y)
if (rootX != rootY) {
if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY
} else if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX
} else {
parent[rootY] = rootX
rank[rootX]++
}
components--
}
}
}
fun main() {
val reader = BufferedReader(InputStreamReader(System.`in`))
val writer = BufferedWriter(OutputStreamWriter(System.out))
// Читаем N и M
val (n, m) = reader.readLine().split(" ").map { it.toInt() }
val edges = Array(m) { IntArray(2) }
for (i in 0 until m) {
val (x, y) = reader.readLine().split(" ").map { it.toInt() }
edges[i] = intArrayOf(x, y)
}
// Читаем запросы
val q = reader.readLine().toInt()
val cuts = reader.readLine().split(" ").map { it.toInt() - 1 } // Переводим в 0-based
val toCut = BooleanArray(m) { false }
for (cut in cuts) {
toCut[cut] = true
}
// Инициализируем DSU
val dsu = DSU(n)
// Добавляем рёбра, которые не будут разрезаны
for (i in 0 until m) {
if (!toCut[i]) {
dsu.union(edges[i][0], edges[i][1])
}
}
// Обрабатываем разрезы в обратном порядке
val result = IntArray(q)
for (i in q - 1 downTo 0) {
result[i] = dsu.components
val edge = edges[cuts[i]]
dsu.union(edge[0], edge[1])
}
// Выводим результат
writer.write(result.joinToString(" "))
writer.newLine()
reader.close()
writer.close()
}