题意
有 n n n 个点,现在已经给出它们的坐标,每过一秒就会向四周扩散一个距离,问什么时候所有扩散的范围会形成一个连通块。
思路
相信聪明的你看到题目就会轻而易举的想到最小生成树。
因为要使它们成为一个连通块,所以就要找出整个最小生成树中的最长边,可以直接跑 kruskal \text{kruskal} kruskal。
至于距离就可以直接用曼哈顿距离来计算。
但是如果直接输出答案,您会发现您 WA \text{WA} WA 了。我们设两个点分别为 A , B A,B A,B,考虑每次扩散,两点一定是同时向对方的方向进行扩散。如果 A A A 扩散一次两点之间曼卡顿距离 − 1 -1 −1, B B B 扩散一次曼哈顿距离也 − 1 -1 −1,这时,其实耗费的时间是两点耗费的时间的和,可是它们却是同时扩散的,所以除以 2 2 2 才应该是正确答案。
代码
#include<bits/stdc++.h>
using namespace std;
int f[100001];
struct edge{
int a,b,w;
bool operator<(const edge W)const{
return w<W.w;
}
}ed[1000001];
int x[1000001],y[1000001];
int n,tot;
int find(int x)
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
int kruskal()
{
int res=-1,cnt=0;
for(int i=1;i<=tot;i++)
{
if(cnt==n-1) break;
int p=find(ed[i].a),q=find(ed[i].b);
if(p!=q)
{
f[q]=p;
cnt++;
res=max(ed[i].w,res);
}
}
return (res+1)/2;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=n;i++)
scanf("%d %d",&x[i],&y[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
ed[++tot]={i,j,abs(x[i]-x[j])+abs(y[i]-y[j])};
sort(ed+1,ed+tot+1);
printf("%d",kruskal());
return 0;
}