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 }
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/Renyi-Fan/p/7604644.html