浙大PAT 1013题 1013. Battle Over Cities

实质就是判断有几个联通子集,400ms的时限。可以用BFS或者DFS或者并查集,效率当然是并查集最高。

我用BFS暴力320ms过了,练习了C++ STL的QUEUE,代码如下:

#include<iostream>
#include<queue>
using namespace std;
int rel[1005][1005];
int main(){
	int i,j,k,N,M,K;
	int from,to,occ;
	int vst[1005];
	cin>>N>>M>>K;
	for(i=1;i<=N;i++){
		for(j=1;j<=N;j++){
			rel[i][j]=0;
		}	
	}
	for(i=1;i<=M;i++){
		cin>>from>>to;
		rel[from][to]=rel[to][from]=1;
	}
	for(i=1;i<=K;i++){
		cin>>occ;
		for(j=1;j<=N;j++){
			vst[j]=0;
		}
		vst[occ]=1;
		int cnt=0;		
		for(j=1;j<=N;j++){
			if(!vst[j]){
				vst[j]=1;
				cnt++;
				queue<int>q;
				q.push(j);
				while(!q.empty()){
					int tmp=q.front();  
                    q.pop();  
					for(k=1;k<=N;k++){
						if(!vst[k]&&rel[tmp][k]){
							vst[k]=1;
							q.push(k);
						}
					}
				}
			}
			
		}
		cout<<cnt-1<<endl;
	}
	return 0;
}


DFS,150ms暴力通过

#include<stdio.h>
#define max_city 1005
int map[max_city][max_city],mark[max_city];
int n,m,k,repair_city,destroy_city;
void dfs(int cur){
	int i;
	for(i=1;i<=n;i++){
		if(map[cur][i]&&cur!=destroy_city&i!=destroy_city&&!mark[i]){
			mark[i]=1;
			dfs(i);
		}
	}
}
int main(){
	int i,j;
	int from,to,city;
	scanf("%d %d %d",&n,&m,&k);
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++){
			map[i][j]=0;
		}
	}
	for(i=0;i<m;i++){
		scanf("%d %d",&from,&to);
		map[from][to]=map[to][from]=1;
	}
	while(k){
		scanf("%d",&destroy_city);
		repair_city=0;
		for(i=1;i<=n;i++){
			mark[i]=0;
		}
		for(i=1;i<=n;i++){
			if(!mark[i]&&i!=destroy_city){
				repair_city++;
			}
			dfs(i);
		}
		printf("%d\n",repair_city-1);
		k--;
	}
}




而用并查集100ms通过,代码如下:

#include<stdio.h>
#define MAXN 1000
#define MAXE MAXN*(MAXN+1)/2
struct Node{
  int from;
  int to;
}node[MAXE];
int fat[MAXN],siz[MAXN];
int getfat(int x){
	if(fat[x]==x) return x;
	else return fat[x]=getfat(fat[x]);
}
void Union(int a,int b){
	int fa=getfat(a);
	int fb=getfat(b);
	if(fa!=fb){
		if(siz[fa]<=siz[fb]){
			fat[fa]=fb;
			siz[fb]+=siz[fa];
		}
		else{
			fat[fb]=fa;
			siz[fa]+=siz[fb];		
		}
	}
}
int main(){
  int i,j,cut;
  int n,m,k;
  scanf("%d %d %d",&n,&m,&k);
  for(i=0;i<m;i++){
    scanf("%d %d",&node[i].from,&node[i].to);
  }
  for(i=0;i<k;i++){
	  for(j=1;j<=n;j++){
		  fat[j]=j;
		  siz[j]=1;
	  }
	  scanf("%d",&cut);
	  for(j=0;j<m;j++){
		  if(node[j].from==cut||node[j].to==cut) continue;
		  if(fat[node[j].from]==fat[node[j].to]) continue;
		  Union(node[j].from,node[j].to);
	  }
	  int cnt=0;
	  for(j=1;j<=n;j++){
		  if(j!=cut&&fat[j]==j){
			  cnt++;			
		  }
	  }
	  printf("%d\n",cnt-1);
  }
  return 0;
} 



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值