QHROAD - Phá đường

Tags: dsu, greedy

Problem

https://vn.spoj.com/problems/QHROAD

https://oj.vnoi.info/problem/QHROAD

Đất nước nọ có N thành phố và M con đường 2 chiều, mỗi con đường nối 2 thành phố. Chú ý là giữa hai thành phố có thể có nhiều con đường khác nhau nối giữa chúng, và cũng có những con đường nối 1 thành phố với chính nó (dùng cho du lịch chẳng hạn, đi loanh quanh chơi rồi trở về thành phố).

Một nhóm các thành phố được gọi là một vùng liên thông nếu:

  • Bất kì 2 thành phố nào trong nhóm cũng đi đến được với nhau
  • Không thể thêm bất kì một thành phố nào khác vào nhóm

Một ngày, đất nước bị giặc ngoại xâm đến xâm lược. Địch rất đông và nguy hiểm, người ta quyết định phá đi Q con đường để làm chậm bước tiến của quân thù.

Có một câu hỏi được đặt ra cho bạn là sau khi phá xong mỗi con đường, số vùng liên thông là bao nhiêu.

Dữ liệu

  • Dòng 1: Ba số nguyên N, M, Q. (1 ≤ N, M ≤ 10^5, 1 ≤ Q ≤ M).
  • Dòng thứ i trong M dòng tiếp theo, mỗi dòng chứa 2 số xi, yi với ý nghĩa: con đường thứ i nối 2 thành phố xiyi.
  • Dòng thứ i trong Q dòng tiếp theo, mỗi dòng chứa số idi là số hiệu của con đường bị phá. (Dữ liệu đảm bào là không có chuyện phá lại con đường đã phá).

Kết quả

  • Gồm Q dòng, dòng thứ i trong Q dòng này là số vùng liên thông sau khi phá con đường idi.

Ví dụ

Input
4 4 3  
1 2  
2 3  
1 3  
3 4  
2  
4  
3

Output
1  
2  
3
Input
3 1 1  
1 2  
1 

Output
3

Tutorial

Đây là một bài vận dụng giải thuật Disjoint-set (DSU).

Ở một trạng thái của đồ thị (trước khi xóa hoặc sau khi xóa 1 số cạnh nào đó), ta có thể dễ dàng tính được số thành phần liên thông trên đồ thị bằng DSU trong O(M+N) với M là số cạnh hiện tại của đồ thị và N là số đỉnh trên đồ thị.

Tuy nhiên với Q truy vấn, ta ko thể thực hiện lại DSU ở từng truy vấn để tính kết quả. Ở đây ta sử dụng 1 trick là tính ngược từ trạng thái sau cùng của đồ thị sau khi xóa hết Q cạnh mà đề bài đặt ra. Duyệt ngược từng truy vấn thì đồ thị sẽ thêm lần lượt từng cạnh và ta tính được kết quả ở từng truy vấn trong O(1). Cụ thể như sau:

  • DSU từ M-Q cạnh của đồ thị, tập cạnh M \ {Q_id_i}, i = 1..Q.
  • Thêm cạnh Q_id_Q vào đồ thị, ta đc DSU M-Q+1 cạnh, tập cạnh M \ {Q_id_i}, i = 1..Q-1.
  • Thêm cạnh Q_id_1 vào đồ thị, ta đc DSU M cạnh, tập cạnh M, là đồ thị ban đầu.

Độ phức tạp: O(N+M).


Submission

QHROAD.cpp