题意后面在来补充
离散化+并查集
虽然我现在还是没太明白为什么用并查集,我觉得就是当find(a) == find(b)
的时候就相当于是有个环了,就可以清空了。
对于离散化我现在还有点不清楚,上次看了y总的板子也没有深入理解先在复习下离散化的知识
离散化
步骤
- 排序
- 去重
- 二分索引
vector<int> alls; // 存储所有待离散化的值
sort(alls.begin(), alls.end()); // 将所有值排序
alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重复元素
// 二分求出x对应的离散化的值
int find(int x) // 找到第一个大于等于x的位置
{
int l = 0, r = alls.size() - 1;
while (l < r)
{
int mid = l + r >> 1;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r + 1; // 映射到1, 2, ...n
}
写了很久,还是没过,有点难受,不知道是哪里错了,但是思路是这个思路等以后再看,重新写一遍把,代码先放在这里
#include <bits/stdc++.h>
using namespace std;
///Invoking the Magic
const int N = 1e5 +10;
int a[N];///原数组
int b[N];///原数组
int d[N];///并查集
int cnt[N];
vector<int> v;
void file()
{
#ifdef ONLINE_JUDGE
#else
freopen("D:/workProgram/test.txt","r",stdin);
//freopen("D:/LSNU/codeforces/duipai/WA.txt","w",stdout);
#endif
}
int Find(int x)
{
int l = 0, r = v.size() - 1;
while( l < r ){
int mid = (l + r ) >> 1;
if( v[mid] >= x ) r = mid;
else l = mid + 1;
}
return r;
}
int Search(int x)
{
if(d[x] != x) d[x] = Search(d[x]);
return d[x];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
file();
int n ;
cin >> n;
while(n--){
int m;
cin >> m;
///离散化
for(int i = 0; i < m ; i++){
cin >> a[i] >> b[i];
v.push_back(a[i]);
v.push_back(b[i]);
}
sort(v.begin(),v.end());
v.erase( unique(v.begin(),v.end()) , v.end());
// cout << v.size();
// for(int i = 0 ; i < v.size() ; i++){
// cout << v[i] << endl;
// }
for(int i = 0 ;i < m ; i++){
d[i] = i;
cnt[i] = 1;
}
///并查集
for(int i = 0 ; i < m; i++){
a[i] = Find(a[i]);
b[i] = Find(b[i]);
//cout << a[i] << " " << b[i] << endl;
}
int ans = 0;
for(int i = 0; i < m ;i++){
int fa = Search(a[i]);
int fb = Search(b[i]);
if(fa != fb){
d[fa] = fb;
cnt[fb] += cnt[fa];
ans = max( ans,cnt[fb] );
}
}
cout << ans << endl;
}
return 0;
}