L2-013 红色警报 并查集
生活随笔
收集整理的這篇文章主要介紹了
L2-013 红色警报 并查集
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目連接
題解:連通塊問題顯然要與并查集有關,而且C4比賽極喜歡出與并查集有關的知識。
這道題可以這樣做,即我每次去掉一個城市的時候,都對剩余的城市重新建立并查集,然后判斷聯通塊的數量有沒有刪減,如果聯通塊的數量沒變說明沒有破壞連通性,而如果改變了說明破壞了連通性,這樣雖然很暴力,時間復雜度很高,但是仍然能過。。。不得不說數據很弱。
當然這道題也可以這樣做,由于當攻陷一個城市的時候,我們需要把并查集分開,但這顯然是不現實的,我們可以逆向思維,即倒著想。先將攻打到最后剩余的城市用并查集聯通起來,然后倒著考慮每一個被攻打的城市,把這個城市加入到城市網絡里,如果并查集合并次數大于1,那么說明這個城市的刪除會導致連通性的破壞,那么發出警報。如果合并次數等于1,說明該城市被攻陷不會破壞連通性,因此不需要發出警報。另外需要注意,輸出信息需要保存在棧中,在判斷結束后,逆序輸出生成的信息。
另外,我的代碼第一次提交的時候只得了21分,原因是把兩個城市加入并查集的時候忘記 判斷之間有沒有道路了。。。這么嚴重的問題都能得21分,可見數據只弱。。。
代碼:
#include <cstdio> #include <string> #include <iostream> #include <stack> using namespace std; const int MAX = 505; int G[MAX][MAX]; int N,M; int parent[MAX]; int rem[MAX]; stack<int> stk; stack<string> outstk; void init() {for(int i = 0;i < MAX;i++) parent[i] = i; } int find(int x) {if(parent[x] == x) return x;return parent[x] = find(parent[x]); } bool join(int x1,int x2) {int p1 = find(x1);int p2 = find(x2);if(p1 != p2) {parent[p1] = p2; return true;}return false; } int main() {init();scanf("%d%d",&N,&M);for(int i = 0;i < M;i++){int u,v;scanf("%d%d",&u,&v);G[u][v] = G[v][u] = 1;}int K;scanf("%d",&K);if(K == N) outstk.push("Game Over.\n");while(K--){int c;scanf("%d",&c);rem[c] = 1;stk.push(c);}for(int i = 0;i < N;i++) if(!rem[i]) for(int j = 0;j < N;j++) if(!rem[j] && G[i][j]) join(i,j);while(!stk.empty()){int u = stk.top();stk.pop();rem[u] = 0;int cnt = 0;for(int i = 0;i < N;i++)if(!rem[i] && G[u][i])if(join(u,i))cnt++; if(cnt >= 2){char tmp[100];sprintf(tmp,"Red Alert: City %d is lost!\n",u);outstk.push(tmp);}else{char tmp[100];sprintf(tmp,"City %d is lost.\n",u);outstk.push(tmp);}}while(!outstk.empty()){cout<<outstk.top();outstk.pop();} }總結
以上是生活随笔為你收集整理的L2-013 红色警报 并查集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 流金岁月哪个台播 流金岁月的播出平台
- 下一篇: 礼品盒制作方法 礼品盒如何制作