20200628 T3 网络检查

Posted poi-bolg-poi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20200628 T3 网络检查相关的知识,希望对你有一定的参考价值。

题目描述

( ext{L}) 是一位网络爱好者,( ext{TA})(n) 台能接入网络的设备,编号为 (1,2,dots,n);还有 (m) 条连接它们的线缆,编号为 (1,2,dots,m)。每条线缆都可以在连接的两台设备间双向传输数据。

在建成网络之后,小 ( ext{L}) 开始担心网络的安全问题。( ext{TA}) 希望测试一下这个网络的抗干扰能力,于是准备了 (q) 次测试:给定两个参数 (l_i)(r_i),小 ( ext{L})会询问当所有编号在 (l_i)(r_i) 之间的线缆都断开的时候,整个网络会分成多少块,满足同一块内的任意两台设备都能互相发送数据,而不同块间的任意两台设备都不能互相发送数据。注意测试之间是相互独立的,在某次测试中断开的线缆会在这一次测试结束后立即再连回去。

( ext{L}) 马上开始动手测试,但 ( ext{TA}) 发现工作量实在太大了,自己完不成,于是 ( ext{TA}) 找到了你。请你根据小 ( ext{L}) 给出的网络描述和测试描述,回答每次测试的结果。

输入格式

第一行输入两个正整数 (n)(m),表示网络中的设备数和线缆数。

接下来 (m) 行,第 (i) 行包含两个正整数 (x)(y)(x eq y)),表示编号为 (i) 的线缆连接了编号为 (x)(y) 的设备。两台设备间可能有多于一条线缆。

下一行包含一个正整数 (q),表示测试的个数。接下来 (q) 行,每行两个正整数 (l_i)(r_i),描述一次测试。

输出格式

输出 (q) 行,每行一个正整数,描述对应测试的结果。

样例

1.in

3 4
1 2
2 3
1 3
3 1
3
1 2
2 4
3 4

1.out

2
2
1

2.in

6 5
1 2
5 4
2 3
3 1
3 6
6
1 3
2 5
1 5
5 5
2 4
3 3

2.out

4
5
6
3
4
2

数据范围与约定

对于 (30\%) 的数据,(n leq 50,m,q leq 1000)

对于另外 (30\%) 的数据,只有不超过 (100) 个不同的 (l_i)

对于 (100\%) 的数据,(2 leq n leq 500,1 leq m leq 10^4,1 leq q leq 2 * 10 ^ 4)

题解

并查集。把全部的边从前往后扫一遍,找到能让不连通的两块变得连通的几条边,从后往前也进行一遍。这样我们就找到了从前往后以及从后往前第一条能使 (u)(v) 两个不连通的块变得连通的边,对于每次断边 ([l,r]) ,我们从之前存下的从前往后以及从后往前第一条能使 (u)(v) 两个不连通的块变得连通的边中找到不在 ([l,r]) 中的边用并查集维护一下最后看有多少个块就行了。

Code

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define MAXN 10001

int n, m, q, u[MAXN], v[MAXN];
int fa[501], size[501];
int pf[MAXN], sf[MAXN];

int find(int x) {
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

void Union(int x, int y) {
	int rootx = find(x), rooty = find(y);
	if (rootx == rooty) return;
	if (size[rootx] > size[rooty]) {
		size[rootx] += size[rooty];
		fa[rooty] = rootx;
	}
	else {
		size[rooty] += size[rootx];
		fa[rootx] = rooty;
	}
}

int main() {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; ++i) fa[i] = i, size[i] = 0;
	for (int i = 1; i <= m; ++i) {
		scanf("%d %d", &u[i], &v[i]);
	}
	for (int i = 1; i <= m; ++i) {
		if (find(u[i]) != find(v[i])) {
			Union(u[i], v[i]);
			pf[++pf[0]] = i;
		}
	}
	for (int i = 1; i <= n; ++i) fa[i] = i, size[i] = 0;
	for (int i = m; i >= 1; --i) {
		if (find(u[i]) != find(v[i])) {
			Union(u[i], v[i]);
			sf[++sf[0]] = i;
		}
	}
	scanf("%d", &q);
	for (int i = 1, x, y, ans = 0; i <= q; ++i) {
		for (int j = 1; j <= n; ++j) fa[j] = j, size[j] = 0;
		scanf("%d %d", &x, &y), ans = 0;
		for (int j = 1; j <= pf[0] && pf[j] < x; ++j) {
			Union(u[pf[j]], v[pf[j]]);
		}
		for (int j = 1; j <= sf[0] && sf[j] > y; ++j) {
			Union(u[sf[j]], v[sf[j]]);
		}
		for (int j = 1; j <= n; ++j) {
			if (fa[j] == j) ++ans;
		}
		printf("%d
", ans);
	}
	return 0;
}

以上是关于20200628 T3 网络检查的主要内容,如果未能解决你的问题,请参考以下文章

20200628 T2 等差数列 To Be Continued

检查网络连接时 getSystemService() 上的 NullPointerException [关闭]

xml Eclipse模板(代码片段)检查参数并最终抛出IllegalArgumentException

VSCode自定义代码片段14——Vue的axios网络请求封装

VSCode自定义代码片段14——Vue的axios网络请求封装

VSCode自定义代码片段14——Vue的axios网络请求封装