1013 Battle Over Cities(并查集解法)

Posted CSU迦叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1013 Battle Over Cities(并查集解法)相关的知识,希望对你有一定的参考价值。

关于背景的介绍见1013 Battle Over Cities(图的DFS解法)

DFS就是不算特定结点后数连通子图的总数,再减一。我想着那么并查集就是数不算特定节点后,集合元素(根)的个数。但是我弄错了一件事,我是边输入,边合并,然后对于每一个占领城市的输入,再绕过那座城市,这样是会出问题的,因为被占领城市很可能被算作了根节点。

正确做法是:依然设置一个邻接表,对于每个占领城市的输入,绕开它把其他存在边的结点合并,再数集合元素的个数,最后减一。

AC代码

#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<cstring>
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#include<cmath>
typedef long long LL;

using namespace std;

const int maxn = 1010;//总城市数上限 

int allCityNum,lostIdx;

vector<int> G[maxn];

int F[maxn];

void initF(){
	for(int i=1;i<=allCityNum;i++)F[i] = i;
} 

int findSo(int x){
	int a = x;
	
	while(x!=F[x]){
		x = F[x];
	}
	
	while(a!=F[a]){
		int z = a;
		a = F[a];
		F[z] = x;
	}
	
	return x;
}

void unite(int a,int b){
	int sa = findSo(a);
	int sb = findSo(b);
	if(sa!=sb){
		F[sa] = sb;
	}
}

int main(){

	int wayNum,lostCityNum;
	scanf("%d %d %d",&allCityNum,&wayNum,&lostCityNum);
	
	for(int i=0;i<wayNum;i++){
		int ct1,ct2;
		scanf("%d %d",&ct1,&ct2);
		G[ct1].push_back(ct2);
		G[ct2].push_back(ct1);
	}
	
	set<int> roots;
	for(int i=0;i<lostCityNum;i++){
		scanf("%d",&lostIdx);
	
		initF();
		roots.clear();
		
		for(int j=1;j<=allCityNum;j++){
			if(j==lostIdx)continue;
			for(int k=0;k<G[j].size();k++){
				int u = G[j][k];
				if(u!=lostIdx)unite(j,u);
			}	
		}
		
		for(int j=1;j<=allCityNum;j++){
			if(j!=lostIdx){
				int sj = findSo(j);
				roots.insert(sj);
			}
		}
		
		printf("%d\\n",roots.size()-1);
	}
	
	
	return 0;
}

以上是关于1013 Battle Over Cities(并查集解法)的主要内容,如果未能解决你的问题,请参考以下文章

PAT 1013. Battle Over Cities

PAT1013. Battle Over Cities(邻接矩阵邻接表分别dfs)

PAT1013: Battle Over Cities

1013 Battle Over Cities(并查集解法)

1013 Battle Over Cities

pat 1013 Battle Over Cities(25 分) (并查集)