码迷,mamicode.com
首页 > 其他好文 > 详细

MNNU10月个人训练赛2

时间:2020-10-16 11:27:12      阅读:16      评论:0      收藏:0      [点我收藏+]

标签:可靠性   out   检查   oid   之间   sign   fine   没有   for   

A.

原题链接

点我跳转

题目

机房的电脑有n台,编号1 - n,开始的时候都是独立的,后面我们对这些电脑进行了m次的连接编号1 - m,每次将a号电脑和b号电脑连接起来。现在Carerd要检查连接的可靠性。 现在有q次询问,每次Carered会暂时断掉编号在[L,R]中的连接,他想知道断开后有多少组计算机?(俩台电脑之间存在连接则俩台电脑视为一组,没有连接其他电脑的电脑单独视为一组),询问过后被断开的连接会被恢复。

解题思路

建立下标为1到m的l[i],代表使用了1到i序号的连线后的并查集,用l[i]存储结果,再建立下标为m到1的r[i],代表使用了i到m序号的连线后的并查集,用r[i]存储结果。查询时,将两端并查集的结果合并即可。

AC_CODE

#include<bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define int long long

using namespace std;

const int N = 5e2 + 10, M = 2e4 + 10;

struct node{
	int fa[N];
	int find(int x){
		if (fa[x] != x) return fa[x] = find(fa[x]);
		return fa[x];
	}
	void up(int x, int y){
		int fx = find(x);
		int fy = find(y);
		if (fx != fy) fa[fy] = fx;
	}
};
node l[M],r[M];
signed main()
{
	int n,m = 0;
	int u[M],v[M];
	while(cin >> n >> m){
		rep(i,1,m) cin >> u[i] >> v[i];
		for (int i = 1; i < N; i++) l[0].fa[i] = i,r[m+1].fa[i] = i;
		rep(i,1,m){
			l[i] = l[i-1];
			l[i].up(u[i],v[i]);
		} 
		per(i,m,1){
			r[i] = r[i+1];
			r[i].up(u[i],v[i]); 
		}
		int q;
		cin >> q;
		while(q--){
			int a , b;
			int ans = 0;
			cin >> a >> b;
			node lt = l[a-1], rt = r[b+1];
		        for(int i = 1; i <= n; i++)
		              lt.up(i,rt.find(i));
		        for(int i = 1; i <= n; i++)
		    	      if(lt.find(i) == i) ans++;   
		        cout << ans << ‘\n‘;
		}
	}
    return 0;
}

MNNU10月个人训练赛2

标签:可靠性   out   检查   oid   之间   sign   fine   没有   for   

原文地址:https://www.cnblogs.com/zhengyongjin/p/13823949.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有 京ICP备13008772号-2
迷上了代码!