【來源】
一本通題庫-1437
LibreOJ-10015
計蒜客-T1882
vjudge
【題目描述】
一個點每過一個單位時間就會向 4 個方向擴散一個距離,如圖所示:兩個點 a 、b 連通,記作 ,當且僅當 a 、b 的擴散區域有公共部分。連通塊的定義是塊內的任意兩個點 u、v 都必定存在路徑 。
給定平面上的 n 個點,問最早什麼時候它們形成一個連通塊。
【輸入格式】
第一行一個數 n ,以下 n 行,每行一個點座標。
【輸出格式】
輸出僅一個數,表示最早的時刻所有點形成連通塊。
【樣例輸入】
2
0 0
5 5
【樣例輸出】
5
【數據範圍】
對於 的數據,滿足 ;
對於 的數據,滿足 。
【解析】
二分答案,並用並查集維護是否聯通。
詳細點說就是每次暴力枚舉兩個點,判斷在當前時間是否聯通,如果聯通就在並查集裏連接。
【代碼】
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
const int N=55;
const int inf=1e9;
struct Node {
int x,y;
} a[N];
int n;
int fa[N];
int d[N][N];
inline int getfa(int x) {
return fa[x]==x ? x : fa[x]=getfa(fa[x]);
}
inline int check(int x,int y) {
int a=getfa(x),b=getfa(y);
if(a==b) return 0;
fa[a]=b;
return 1;
}
inline void f(int l,int r) {
if(l+1==r) {
printf("%d\n",r);
exit(0);
}
int mid=(l+r)>>1;
for(int i=1; i<=n; i++) fa[i]=i;
int k=n;
for(int i=1; i<=n; i++) for(int j=i+1; j<=n; j++)
if(d[i][j]<=(mid<<1)) if(check(i,j)) k--;
if(k==1) f(l,mid);
else f(mid,r);
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++) scanf("%d%d",&a[i].x,&a[i].y);
for(int i=1; i<=n; i++) for(int j=i+1; j<=n; j++)
d[i][j]=d[j][i]=abs(a[i].x-a[j].x)+abs(a[i].y-a[j].y);
f(0,inf);
return 0;
}