题目链接:
https://codeforces.com/problemset/problem/1609/D
题目大意:
有 \(n\) 个人参与会议,他们相互之间不认识,\(William\) 有 \(d\) 条介绍关系,每条关系就是让参加会议的 \(x\) 和 \(y\) 这两个人相互认识,输出 \(Willian\) 每介绍一条关系后参加会议的一个人最多能认识多少人。
思路:
建立两个人的关系,可以想到并查集,将两者建立联系,然后更新两个人的数量。
但是还有一种情况,如果 \(William\) 介绍的两个人已经认识了,那就意味着这个关系已经没用了,我们可以任意指定两个人相互认识(题目中好像没说,或者我没读明白题目 \(qwq\),我是从官方题解里面悟出来的)。
在这种情况下,我们需要统计可以任意指定的次数,然后为了使一个人认识最多人,那么我们就要选择认识人数多的那几个人互相认识,这样子才会使结果最大。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int fa[N], x, y, n, d, p = 1, num[N], t[N];
int find(int k){
if (k != fa[k]) fa[k] = find(fa[k]);
return fa[k];
}
void unit(int a, int b){
int p = find(a);
int q = find(b);
fa[q] = p;
num[p] += num[q];
num[q] = 0; //更新认识的人数
}
int main(){
cin >> n >> d;
for (int i = 1; i <= n; i++){
fa[i] = i;
num[i] = 1;
}
for (int i = 1; i <= d; i++){
scanf("%d %d", &x, &y);
if (find(x) == find(y)) p++;
else unit(x, y);
for (int i = 1; i <= n; i++)
t[i] = num[i];
sort(t + 1, t + n + 1, greater<int>() ); //从大到小排序
int ans = t[1] - 1; //统计一个人能认识多少人,所以自己不算在内
for (int i = 2; i <= p; i++)
ans += t[i];
cout << ans << "\n";
}
return 0;
}