ACcoders Problem 2047 题解

题意

n n n 个点,现在已经给出它们的坐标,每过一秒就会向四周扩散一个距离,问什么时候所有扩散的范围会形成一个连通块。

思路

相信聪明的你看到题目就会轻而易举的想到最小生成树。

因为要使它们成为一个连通块,所以就要找出整个最小生成树中的最长边,可以直接跑 kruskal \text{kruskal} kruskal

至于距离就可以直接用曼哈顿距离来计算。

但是如果直接输出答案,您会发现您 WA \text{WA} WA 了。我们设两个点分别为 A , B A,B A,B,考虑每次扩散,两点一定是同时向对方的方向进行扩散。如果 A A A 扩散一次两点之间曼卡顿距离 − 1 -1 1 B B B 扩散一次曼哈顿距离也 − 1 -1 1,这时,其实耗费的时间是两点耗费的时间的和,可是它们却是同时扩散的,所以除以 2 2 2 才应该是正确答案。

代码

#include<bits/stdc++.h>
using namespace std;
int f[100001];
struct edge{
    int a,b,w;
    bool operator<(const edge W)const{
        return w<W.w;
    }
}ed[1000001];
int x[1000001],y[1000001];
int n,tot;
int find(int x)
{
    if(f[x]==x) return x;
    return f[x]=find(f[x]);
}
int kruskal()
{
    int res=-1,cnt=0;
    for(int i=1;i<=tot;i++)
	{
        if(cnt==n-1) break;
		int p=find(ed[i].a),q=find(ed[i].b);
		if(p!=q)
		{
			f[q]=p;
			cnt++;
			res=max(ed[i].w,res);
		}
	}
	return (res+1)/2;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=n;i++)
        scanf("%d %d",&x[i],&y[i]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<i;j++)
            ed[++tot]={i,j,abs(x[i]-x[j])+abs(y[i]-y[j])};
    sort(ed+1,ed+tot+1);
    printf("%d",kruskal());
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值