题意分析:看到水滴四个方向扩散第一感觉和 OJ 19120 病毒扩散( ★ ★) 很相似,是否用BFS算法解决问题,但是如果模拟二维数组xi和yi范围比较大,因此不可行。鉴于数据规模较小,因此可否有一种贪心策略检查任意两点距离,找出某个值...........继续思考没有可证明的贪心思路。
由于题目要求是连通问题,且任意两点最终一定可以连通,而整体数据可以看成是一个完全图。在完全图中确定一个最小连通代价,即最小生成树问题。最小生成树中最长的边就是问题的解。
使用并查集辅助的克鲁斯卡尔算法实现。
#include <bits/stdc++.h>
using namespace std;
struct node /**< 边存储结构 */
{
int x,y,len;
bool operator<(const node B)const
{
return len<B.len;
}
};
vector<node>e;/**< 边集合 */
int i,j,a[1005],b[1005],n,f[1005],cnt=0;
int findx(int x)/**< 并查集函数 */
{
return f[x]==x?x:f[x]=findx(f[x]);
}
int main()
{
cin>>n;
for(i=1;i<=n;i++)/**< 并查集初始化 */
f[i]=i;
for(i=1;i<=n;i++)
cin>>a[i]>>b[i];
for(i=1;i<=n;i++)/**< 将所有的边放入边集合e */
for(j=i+1;j<=n;j++)
e.push_back({i,j,abs(a[i]-a[j])+abs(b[i]-b[j])});
sort(e.begin(),e.end());
for(i=0;i<e.size();i++)/**< 克鲁斯卡尔算法找最小边 */
{
int f1=findx(e[i].x),f2=findx(e[i].y);
if(f1!=f2)
{
f[f1]=f2;
cnt++;
if(cnt==n-1)
break;
}
}
cout<<(e[i].len+1)/2;/**< 最后一次找到的边一定是所有边最长的,其值除2即为解 */
return 0;
}