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 }