本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目链接:
codeforces.com/problemset/…
题意看了好长时间,看不懂,英语太难了😭😭😭
d个条件,到达第i个条件时,要保证前i个条件中的x和y是连通的(不是必须相连),且图中需要共有i条边,求最大连通块的大小
也就是说,如果之前的条件已经让x和y连通了,这次没必要再连接x和y了,可以自由支配连接一条边
对于每次询问x和y:
最后结果为res-1,除去本身
cnt:代表可以自由连接边的条数
ve[]:代表所有连通块大小的数组,之后会对其进行从大到小排序
对于并查集的模板我们还是有必要知道并且熟练掌握的。并查集是平常出题中非常常见的数据结构,不知道它的话基本很多题目都做不了。并查集主要就是一个查找的函数还有一个合并的函数,两个都对原理理解透彻的话才能在平时的做题中游刃有余。
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int N = 1e5+5;
struct dsu
{
vector<int>f,sz;
dsu(int n)
{
f.resize(n);
sz.resize(n,1);
for(int i=0;i<n;i++) f[i] = i;
}
void merge(int x,int y)
{
x = find(x);
y = find(y);
if(x == y) return;
if(x > y) swap(x,y);
f[y] = x;
sz[x] += sz[y];
sz[y] = 0;
}
int find(int x)
{
return f[x]==x ? x : f[x]=find(f[x]);
}
};
void solve()
{
int n,m;
cin>>n>>m;
dsu tr(n+1);
int cnt = 0;
while(m--)
{
int u, v;
cin>>u>>v;
int x = tr.find(u);
int y = tr.find(v);
if(x == y) cnt ++;
else tr.merge(x,y);
vector<int> ve;
for(int i=1;i<=n;i++)
if(tr.sz[i]) ve.push_back(tr.sz[i]);
sort(ve.begin(),ve.end(),greater<int>());
int res = 0;
for(int i=0;i<=cnt and i<ve.size();i++)
res += ve[i];
cout<<res - 1<<endl;
}
}
int main()
{
int t;
// cin>>t;
t = 1;
while(t--) solve();
return 0;
}