逆向並查集

2021-10-25 08:46:03 字數 1722 閱讀 1355

題目: 題目.

題意:有n個戰艦(0~n-1),每個戰艦有乙個戰鬥力,然後輸入乙個m表示m對戰艦聯合,然後輸入乙個q表示q次查詢。接下來q行有兩種輸入:1、query x 表示查詢和x戰艦聯合對戰艦中攻擊力最大的戰艦的編號(如果戰鬥力相同輸出小的編號),如果沒有就輸出-1. 2、destroy x y 破壞x戰艦和y戰艦的關係,不改變其他戰艦關係。

知道這題的思路的時候感覺發現了新大陸,太強了。。。

思路:如果直接先把m組關係處理完然後正向的操作q次操作,會很難處理destroy的操作,因為既要保持已有的關係,並且刪除x和y的關係,很難維護。所以改變一下思路,先存下m對關係和q次操作,並標記一下被destroy的關係,接著合併關係的時候先實現最終的情況,也就是destroy過的關係如果出現在m對關係中,先不聯合,當碰到destroy的時候才把它聯合,就是反著操作。注意輸出的時候也要反著輸出。

**:

#include 

#include

#include

#include <

set>

#include

#include

#include

#include

#include

#include

using namespace std;

#define ll long long

#define inf 0x3f3f3f3f

#define pb push_back

#define t int t

;scanf

("%d",&

t);while(t

--)const ll mod=

1e9+7;

const int maxn =

2e5+5;

int p[maxn]

;//戰鬥力

struct nodea[maxn]

;//m對關係

struct node1aa[maxn]

;//q次操作

int f[maxn]

;int n;

int find

(int x)

void

com(int x, int y)

else}}

int main()

for(int i =

0; i < n+5;

++i)

int m;

string s;

map,int> vis;

scanf

("%d"

,&m)

;for

(int i =

1; i <= m; i++

) int q;

scanf

("%d"

,&q)

;for

(int i =

1; i <= q; i ++

)else

}//開始進行戰艦的聯合

for(int i =

1; i <= m; i ++)}

stack ans;

for(int i = q; i >=

1; i --

)else ans.

push(-

1);//沒有就輸出-1

}else

}while

(!ans.

empty()

)}return0;

}/**/

C City 逆向並查集

時間限制 1 s 記憶體限制 128 mb 如果城市a和城市b互通,城市b和城市c互通,那麼城市a和城市c也互通,a b c三個城市算乙個聚集點。先已知有n個城市和m條道路,想求的是有幾個聚集點?但小s覺得太簡單了,由於戰爭原因,某些城市會被飛彈銷毀掉,與之相應的道路也變得不可用。之前已經被銷毀的不...

逆向並查集(ZOJ 3261)

與並查集不同,給出乙個圖中原有的一些邊,然後給出操作,操作不是向圖中新增邊,而是在已有的邊上,將邊刪除。對於該種情況,需要把首先讀入所有操作,把要求刪除的邊全部刪除,再按照從後往前的順序處理操作,這樣刪邊操作又重新轉化為了添邊的操作。例題 zoj3261 connections in galaxy ...

zoj 3261 逆向並查集

很明顯是逆向的並查集,建立邊再銷毀,思路也很巧妙的逆向思考 如果正著一一銷毀,相當於倒著一一建邊。所以儲存q次提問,最後倒著來一一建邊。在此之前先把沒有銷毀的邊全部建好 細節power能量注意一下 view code 1 include 2 include 3 include 4 include 5...