• 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;
    }
    
  • 相关阅读:
    新闻发布项目——Servlet类(doRegServlet )
    新闻发布项目——Servlet类(doNewsModifyServlet )
    新闻发布项目——Servlet类(doNewsModifyServlet )
    新闻发布项目——Servlet类(doNewsModifyServlet )
    and or 逻辑组合
    sqoop
    t
    tmp
    临时表 数据在 内存 转移时间 将160秒的创建临时表时间放入定时任务 不到1秒的求和时间 hadoop 引入Hadoop 分布式计算
    /tmp/crontab.tDoyrp: 设备上没有空间 查看文件夹所在分区 磁盘剩余空间 15g的root-mail大文件
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13205103.html
Copyright © 2020-2023  润新知