https://www.luogu.org/problemnew/show/P5429
很明显是要维护整个连通块的共同性质,并查集一搞就完事了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=100000;
int par[MAXN+5];
int u[MAXN+5],d[MAXN+5],l[MAXN+5],r[MAXN+5];
void init(int n) {
for(int i=1; i<=n; i++) {
par[i]=i;
}
}
int find_par(int x) {
int k,pk,r;
r=x;
while(r!=par[r])
r=par[r]; //x查到根,保存为r
k=x;
while(k!=r) { //循环处理x的祖先直到根
pk=par[k]; //保存k的父亲后把k接入r
par[k]=r;
k=pk; //处理k的父亲
}
return r;
}
bool union_set(int x,int y) {
int fx=find_par(x);
int fy=find_par(y);
if(fx==fy) {
return false;
} else {
par[fy]=fx;
u[fx]=max(u[fx],u[fy]);
d[fx]=min(d[fx],d[fy]);
l[fx]=min(l[fx],l[fy]);
r[fx]=max(r[fx],r[fy]);
return true;
}
}
ll calc(int fi){
ll dy=u[fi]-d[fi];
ll dx=r[fi]-l[fi];
return 2ll*(dy+dx);
}
int main() {
#ifdef Yinku
freopen("Yinku.in","r",stdin);
#endif // Yinku
int n,m;
scanf("%d%d",&n,&m);
init(n);
for(int i=1;i<=n;i++){
scanf("%d%d",&l[i],&d[i]);
r[i]=l[i],u[i]=d[i];
}
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
union_set(x,y);
}
ll ans=1e18;
for(int i=1;i<=n;i++){
int fi=find_par(i);
ans=min(ans,calc(fi));
}
printf("%lld
",ans);
return 0;
}