列表

详情


NC219798. NIT的图

描述

NIT 在 n 年前还是普及组选手的时候做过这样一个题目,求一个图的连通块数目,以NIT现在国家队的实力,做这样的题实在是太侮辱他的智商了,于是他思考着加强这道题目。


给你一个 n 个点的图,一开始这个图上有 m 条边。

你需回答共 q 次询问操作。

对于每次询问操作,你将会得到一个数 x ,求出在当前图的基础上加入 x 条边后最多有几个连通块。

输入描述

输入共 m+q+1 行。

第一行 3 个 正整数 n,m,q ,分别表示点数,边数,操作数。

接下来 m 行,每行 2 个正整数 x,y 表示 x,y 之间有一条连边,无重边自环。

接下来 q 行,每行 1 个数为 x 表示在原图上加入 x 条边后最多有几个连通块,不允许加重边,自环,询问之间互不影响。

输出描述

你的输出应有 q 行,每行 1 个正整数 ans,表示这次询问的答案。

示例1

输入:

5 3 3
1 2
1 3
4 5
2
0
7

输出:

1
2
1

说明:

在原图上添加 2 条边时,无论怎样连边都会连成一个连通块,故答案为 1。
在原图上添加 0 条边时,显然连通块数目不变,为 2。
在原图上添加 7 条边时,原图变为完全图,有一个连通块,故答案为 1。

示例2

输入:

7 4 5
6 4
7 1
3 1
5 2
5
8
1
10
17

输出:

2
1
3
1
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 318ms, 内存消耗: 13984K, 提交时间: 2021-06-19 19:15:48

#include<bits/stdc++.h>
using namespace std;

typedef long long s64;
const int N=5e5+5;
int fa[N],sz[N],q[N],t; 
s64 sum[N];
int find(int x){
	return x==fa[x]?x:fa[x]=find(fa[x]);
}
 
int main(){
#ifdef kcz
	freopen("1.in","r",stdin);//freopen("1.out","w",stdout);
#endif
	int n,m,qcnt;
	cin>>n>>m>>qcnt;
	for(int i=1;i<=n;++i){
		fa[i]=i;sz[i]=1;
	}
	for(int i=1;i<=m;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		x=find(x);y=find(y);
		if(x!=y){
			fa[x]=y;sz[y]+=sz[x];
		}
	}
	for(int i=1;i<=n;++i)
	if(fa[i]==i){
		q[++t]=sz[i];
		sum[1]+=sz[i]*s64(sz[i]-1)/2;
	}
	sort(q+1,q+t+1,greater<int>());
	int s=0;
	for(int i=2;i<=t;++i){
		s+=q[i-1];
		sum[i]=sum[i-1]+s*s64(q[i]);
	}
	while(qcnt--){
		s64 x;
		scanf("%lld",&x);
		printf("%d\n",t-(lower_bound(sum+1,sum+t,m+x)-sum)+1);
	}
}

上一题