「一本通 1.2 练习 2」扩散(loj10015)

题目描述

一个点每过一个单位时间就会向 4 个方向扩散一个距离,如图所示:两个点 ab 连通,记作 e(a,b),当且仅当 ab 的扩散区域有公共部分。连通块的定义是块内的任意两个点 uv都必定存在路径

给定平面上的 n 个点,问最早什么时候它们形成一个连通块。

输入格式

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

输出格式

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

样例

样例输入

2
0 0
5 5

样例输出

5

数据范围与提示

对于 20% 的数据,满足 1≤n≤5,1≤Xi,Yi≤50i​​,Yi​​50;

对于 100% 的数据,满足 1≤n≤50,1≤Xi,Yi≤10^9

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 52;
int G[maxn][maxn], n, xx[maxn], yy[maxn];
inline void init(int x){
    for(int i=1; i<=n; ++i){
        for(int j=1; j<=n; ++j)
            G[i][j] = 0;
        G[i][i] = 1;
    }
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j)
            if(abs(xx[i] - xx[j]) + abs(yy[i] - yy[j]) <= x << 1)
                G[i][j] = 1;
}
inline void floyd(){
    for(int k=1; k<=n; ++k)
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                if(G[i][k] && G[k][j])
                    G[i][j] = 1;            
}
inline bool deal(int x){
    init(x);
    floyd();
    int judge = 1;
    for(int i=1; i<=n; i++)    judge &= G[1][i];
    return judge;
}
int main(void)
{
    cin >> n;
    for(int i=1; i<=n; ++i)
        cin >> xx[i] >> yy[i];        
    int l = 1, r = 1000000000;
    while(l < r){
        int mid = (l + r) >> 1;
        if(deal(mid))    r = mid;
        else            l = mid + 1;        
    }    
    cout << l << endl;
}

 思路

  二分+连边建图+floyd

i​​,Yi​​109​​。

猜你喜欢

转载自www.cnblogs.com/junk-yao-blog/p/9469974.html