P1661 扩散

题目描述

一个点每过一个单位时间就会向四个方向扩散一个距离,如图。

P1661 扩散_微信

两个点a、b连通,记作e(a,b),当且仅当a、b的扩散区域有公共部分。连通块的定义是块内的任意两个点u、v都必定存在路径e(u,a0),e(a0,a1),…,e(ak,v)。给定平面上的n给点,问最早什么时刻它们形成一个连通块。

输入输出格式

输入格式:

 

第一行一个数n,以下n行,每行一个点坐标。

【数据规模】

对于20%的数据,满足1≤N≤5; 1≤X[i],Y[i]≤50;

对于100%的数据,满足1≤N≤50; 1≤X[i],Y[i]≤10^9。

 

输出格式:

 

一个数,表示最早的时刻所有点形成连通块。

 

输入输出样例



输入样例#1:

2
0 0
5 5


输出样例#1:

5


 


分析:



离散化,最短距离就是映射在x轴和y轴上的距离和除2。

比如说一个点是(5,0),一个点是(0,4),最短距离就是(|5-0|+|0-4|+1)/2=5

加1保证向上取整。

本题就是求最小生成树的最大边。

 

距离不是严格的曼哈顿距离,应该是

dis[i,j]=(max(x[i]-x[j],x[j]-x[i])+max(y[i]-y[j],y[j]-y[i])-1)/2+1;


可以最小生成树,但是题目可以看出是最小生成树的最大边,所以二分答案应该也可以做,但是二分答案不好调,所以放最小生成树代码。。。

 



1 #include<cstdio>
2 #include<iostream>
3 #include<vector>
4 #include<algorithm>
5 #define mysister
6 using namespace std;
7 const int maxn=50;
8 struct bian
9 {
10 int u,v,w;
11 bian(int a,int b,int c):u(a),v(b),w(c){}
12 bool operator < (bian b)
13 {
14 return w<b.w;
15 }
16 };
17 int n,x[maxn],y[maxn],ans=0,fa[maxn];
18 vector<bian>g;
19 int find(int u)
20 {
21 return fa[u]==u?u:fa[u]=find(fa[u]);
22 }
23 int main()
24 {
25 scanf("%d",&n);
26 for(int i=0;i<n;i++)
27 {
28 scanf("%d%d",&x[i],&y[i]);
29 fa[i]=i;
30 for(int j=0;j<i;j++)
31 g.push_back(bian(i,j,(max(x[i]-x[j],x[j]-x[i])+max(y[i]-y[j],y[j]-y[i])-1)/2+1));
32 }
33 sort(g.begin(),g.end());
34 for(int i=0;i<g.size();i++)
35 if(find(g[i].u)!=find(g[i].v))
36 {
37 fa[find(g[i].u)]=find(g[i].v);
38 ans=max(ans,g[i].w);
39 }
40 printf("%d",ans);
41 }