【CCCC】L2-013 紅色警報 (25分),,並查集計算集合個數

小哈里發表於2020-10-03

problem

L2-013 紅色警報 (25分)
戰爭中保持各個城市間的連通性非常重要。本題要求你編寫一個報警程式,當失去一個城市導致國家被分裂為多個無法連通的區域時,就發出紅色警報。注意:若該國本來就不完全連通,是分裂的k個區域,而失去一個城市並不改變其他城市之間的連通性,則不要發出警報。

輸入格式:
輸入在第一行給出兩個整數N(0 < N ≤ 500)和M(≤ 5000),分別為城市個數(於是預設城市從0到N-1編號)和連線兩城市的通路條數。隨後M行,每行給出一條通路所連線的兩個城市的編號,其間以1個空格分隔。在城市資訊之後給出被攻佔的資訊,即一個正整數K和隨後的K個被攻佔的城市的編號。

注意:輸入保證給出的被攻佔的城市編號都是合法的且無重複,但並不保證給出的通路沒有重複。

輸出格式:
對每個被攻佔的城市,如果它會改變整個國家的連通性,則輸出Red Alert: City k is lost!,其中k是該城市的編號;否則只輸出City k is lost.即可。如果該國失去了最後一個城市,則增加一行輸出Game Over.。

輸入樣例:
5 4
0 1
1 3
3 0
0 4
5
1 2 0 4 3
輸出樣例:
City 1 is lost.
City 2 is lost.
Red Alert: City 0 is lost!
City 4 is lost.
City 3 is lost.
Game Over.
作者
陳越
單位
浙江大學
程式碼長度限制
16 KB
時間限制
400 ms
記憶體限制
64 MB

  • n個點m條邊的圖,隨後按順序割掉k個點,每次判斷剩餘圖的連通性

solution

  • 連通性,很容易想到並查集
  • 每攻打一次城市重新跑一次並查集(不合並已經被攻打的點),如果當前集合個數與上一張圖的集合數相等或者+1則無影響,否則紅色警告。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5050;

int x[maxn], y[maxn], vis[maxn];

int fa[maxn];
void init(int n){for(int i = 0; i < n; i++)fa[i]=i;}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void merge(int x, int y){x=find(x);y=find(y);if(x!=y)fa[x]=y;}
int count(int n){//統計並查集集合個數
	int cnt = 0;
	for(int i = 0; i < n; i++)//節點從0-n編號
		if(fa[i]==i)cnt++;
	return cnt;
}

int main(){
	int n, m;
	cin>>n>>m;
	init(n);
	for(int i = 1; i <= m; i++){
		cin>>x[i]>>y[i];
		merge(x[i],y[i]);
	}
	int k;  cin>>k;
	int cc1=count(n), cc2;
	for(int i = 1; i <= k; i++){
		int t;  cin>>t;
		vis[t] = 1;//被攻佔的不再聯通
		init(n);
		for(int j = 1; j <= m; j++){
			if(vis[x[j]]||vis[y[j]])continue;
			merge(x[j],y[j]);
		}
		cc2 = count(n);
		//cout<<cc2<<endl;
		if(cc2==cc1||cc2==cc1+1)
			printf("City %d is lost.\n",t);
		else 
			printf("Red Alert: City %d is lost!\n",t);
		cc1 = cc2;
	}
	if(k==n)printf("Game Over.\n");
	return 0;
}


相關文章