进阶实验6-3.1 红色警报

题目链接
思路:利用并查集,每次删完结点,统计连通块,如果比原来多了1块及以上,则说明出现连通块分裂,该节点对其他节点有影响,因为我在题目中统计连通块的方式是遍历对于所有结点的root数组,是-1则连通块加一,但删除该点后还是会统计到这个点为连通块,故题目中的判断是删后连通块>原连通块+1。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 5e2+5;
int root[MAX];
bool _map[MAX][MAX];
bool vis[MAX];
int N, M;
int find_root(int x) {
	return root[x] < 0 ? x : root[x] = find_root(root[x]);
}//优化版并查集,会将该节点并到最深入的那个根上
void union_root(int a, int b) {
	a = find_root(a);
	b = find_root(b);
	if (a != b) {
		if (root[a] < root[b]) {
			root[a] += root[b];
			root[b] = a;
		}
		else{
			root[b] += root[a];
			root[a] = b;
		}
	}
}
//将root数组置为-1,负数代表该节点的子节点个数
void init(int N) {
	for (int i = 0; i < N; i++)
		root[i] = -1;
}
int main() {
	int original=0,after=0;
	scanf("%d%d", &N, &M);
	int v, t;
	init(N);
	for (int i = 0; i < M; i++) {
		scanf("%d%d", &v, &t);
		_map[v][t] = 1;
		_map[t][v] = 1;
		union_root(v, t);
	}
	int K,edge;
	for (int i = 0; i < N; i++)
		if (root[i] < 0)
			original++;
	scanf("%d",& K);
	int k = K;
	while (k--) {
		scanf("%d", &edge);
		init(N);
		for (int i = 0; i < N; i++) {//与该点相连的边删去
			_map[i][edge] = 0;
			_map[edge][i] = 0;
		}
		for (int i = 0; i < N; i++)
			for (int j = 0; j < N; j++)
				if (_map[i][j])
					union_root(i, j);
			for (int i = 0; i < N; i++)
				if (root[i] < 0)
					after++;
			if (after>original+1) 
				printf("Red Alert: City %d is lost!\n",edge);
		else
		printf("City %d is lost.\n", edge);
			original = after;
			after = 0;
	}
	if (K == N)
		printf("Game Over.");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值