【题解】 CF1419F Rain of Fire 并查集+二分答案+暴力

Legend

Link \(\textrm{to Codeforces}\)

给定 \(n\ (1 \le n \le 1000)\) 个二维平面上的点,坐标 \((x_i,y_i)\ (|x_i|,|y_i| \le 10^9)\)

两个点 \(i,j\) 可以互相到达当且仅当他们 \(x_i=x_j\) 或者 \(y_i=y_j\)

发现有的情况所有点可能到不了,于是你可以在任意位置设置至多 1 个新点。

同时每隔 \(t\) 秒会有一次轰炸,意思是两个点 \(i,j\) 可以互相到达还要它们之间的距离 \(\le t\)

求出最小的 \(t\),使得所有点可以相互到达,到不了请输出 \(-1\)

Editorial

有显然的可二分性,二分一个 \(t=mid\),然后考虑怎么 \(\rm{check}\) 是否可行。

先不考虑新加点。

\(n\) 很小,让人想到暴力并查集。得到了若干个连通块。

此时考虑新加点。

发现显然连通块个数 \(>4\) 的时候即使加入新点也永远无法连通。

那么对于连通块个数分类讨论一下即可。

连通块个数 \(=1\)

可行。

连通块个数 \(=2\)

暴力枚举不同连通块的两个点 \(i,j\)

  • 如果不在同一行或者同一列,看是不是 \(\max(|x_i-x_j|,|y_i-y_j|) \ge mid\),是就可行;
  • 如果在同一行或者同一列,看是不是距离 \(\le 2mid\),是就可行。

如果不存在上述两种点对,则不可行。

此部分复杂度 \(O(n^2)\)

连通块个数 \(=3\)

一定存在一个点使得它到三个连通块的距离都 \(\le mid\)

设所有的连通块是 \(X,Y,Z\)

枚举两个连通块 \(X,Y\),看看哪些点是可能潜在的新点,最多只有 \(O(n^2)\) 个。

再枚举 \(X,Z\),看看哪些点是可能潜在的新点且与之前 \(X,Y\)潜在的新点重合,如果有重合那么就可行。

那么什么是潜在的新点呢?比如对于下面这个三个点的图:

白色的矩形位置都是潜在的新点,但是只有中排的这个白色矩形才是“粉蓝”,“绿蓝”两组连通块共同的潜在的新点,于是就可以放在这里。

如果我们此时恰好枚举到的是 \(X=蓝,Y=粉,Z=绿\),那么就很幸运的做完了。

但如果不幸枚举到 了\(X=粉,Y=蓝,Z=绿\),那么“粉蓝”,“粉绿”两组连通块就没有找到共同的潜在的新点。

如果没有就轮换 \(X,Y,Z\) 再做,直到 \(3\) 种情况都试完了为止,此时一定不行。

此部分复杂度 \(O(n^2)\)

连通块个数 \(=4\)

一定存在一个点使得它到四个连通块的距离都 \(\le mid\)

设所有的连通块是 \(A,B,C,D\)

跟三个连通块同理,也只要找两个集合枚举潜在的新点,拿另外两个集合检查即可。

只要测试 \(2\) 轮。

此部分复杂度 \(O(n^2)\)


所以加上二分总复杂度 \(O(n^2 \log x)\)

Code

丑陋无比……

#include <bits/stdc++.h>

using namespace std;

#define LL long long

const int MX = 1000 + 233;

int n;

unordered_map<LL ,int> lshx ,lshy;

struct point{
	LL x ,y;
	LL mxd(point b){
		return max(abs(x - b.x) ,abs(y - b.y));
	}
}p[MX];

int fa[MX] ,vis[MX] ,lead[MX];
int tag[MX][MX] ,tc;
void init(){
	for(int i = 1 ; i <= n ; ++i)
		fa[i] = i ,vis[i] = 0;
}
int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);}


LL X[MX] ,Y[MX];
bool check(LL len){
	init();
	for(int i = 1 ; i <= n ; ++i){
		for(int j = i + 1 ; j <= n ; ++j){
			if(p[i].x == p[j].x){
				if(abs(p[i].y - p[j].y) <= len){
					fa[find(i)] = find(j);
				}
			}
			if(p[i].y == p[j].y){
				if(abs(p[i].x - p[j].x) <= len){
					fa[find(i)] = find(j);
				}
			}
		}
	}
	int ltk = 0;
	for(int i = 1 ; i <= n ; ++i){
		if(!vis[find(i)]){
			vis[find(i)] = ++ltk;
			lead[ltk] = find(i);
		}
	}
	if(ltk == 1) return true;

	if(ltk == 2){
		LL dis = LLONG_MAX;
		for(int i = 1 ; i <= n ; ++i){
			if(find(i) != lead[1]) continue;
			for(int j = 1 ; j <= n ; ++j){
				if(find(j) != lead[2]) continue;
				if(p[i].x == p[j].x){
					dis = min(dis ,(abs(p[i].y - p[j].y) + 1) / 2);
				}
				else if(p[i].y == p[j].y){
					dis = min(dis ,(abs(p[i].x - p[j].x) + 1) / 2);
				}
				else dis = min(dis ,p[i].mxd(p[j]));
			}
		}
		return dis <= len;
	}
	if(ltk == 3){
		int qwq[4] = {0 ,1 ,2 ,3};
		for(int T = 1 ; T <= 3 ; ++T){
			++tc;
			swap(qwq[1] ,qwq[T]);
			for(int i = 1 ; i <= n ; ++i){
				if(find(i) != lead[qwq[1]]) continue;
				for(int j = 1 ; j <= n ; ++j){
					if(find(j) != lead[qwq[2]]) continue;
					if(p[i].mxd(p[j]) <= len){	
						tag[lshx[p[i].x]][lshy[p[j].y]] = tc;
						tag[lshx[p[j].x]][lshy[p[i].y]] = tc;
					}
				}
			}
			for(int i = 1 ; i <= n ; ++i){
				if(find(i) != lead[qwq[1]]) continue;
				for(int j = 1 ; j <= n ; ++j){
					if(find(j) != lead[qwq[3]]) continue;
					if(p[i].mxd(p[j]) <= len){
						if(p[i].mxd(p[j]) <= len && 
						(tag[lshx[p[i].x]][lshy[p[j].y]] == tc
						|| tag[lshx[p[j].x]][lshy[p[i].y]] == tc))
							return 1;
					}
				}
			}
		}
		return false;
	}
	if(ltk == 4){
		int qwq[5] = {0 ,1 ,2 ,3 ,4};
		for(int T = 1 ; T <= 2 ; ++T){
			++tc;
			swap(qwq[2] ,qwq[3]);
			for(int i = 1 ; i <= n ; ++i){
				if(find(i) != lead[qwq[1]]) continue;
				for(int j = 1 ; j <= n ; ++j){
					if(find(j) != lead[qwq[2]]) continue;
					if(p[i].mxd(p[j]) <= len){
						tag[lshx[p[i].x]][lshy[p[j].y]] = tc;
						tag[lshx[p[j].x]][lshy[p[i].y]] = tc;
					}
				}
			}
			for(int i = 1 ; i <= n ; ++i){
				if(find(i) != lead[qwq[3]]) continue;
				for(int j = 1 ; j <= n ; ++j){
					if(find(j) != lead[qwq[4]]) continue;
					if(p[i].mxd(p[j]) <= len &&
					(tag[lshx[p[i].x]][lshy[p[j].y]] == tc
					|| tag[lshx[p[j].x]][lshy[p[i].y]] == tc))
						return 1;
				}
			}
		}
		return false;
	}
	return false;
}


int main(){
	cin >> n;
	for(int i = 1 ; i <= n ; ++i){
		cin >> p[i].x >> p[i].y;
		X[i] = p[i].x ,Y[i] = p[i].y;
		lshx[X[i]] = i;
		lshy[Y[i]] = i;
	}
	sort(X + 1 ,X + 1 + n);
	sort(Y + 1 ,Y + 1 + n);
	LL l = 0 ,r = 2e9 + 1 ,mid;
	while(l <= r){
		mid = (l + r) >> 1;
		if(check(mid)) r = mid - 1;
		else l = mid + 1;
		// cerr << l << " " << r << endl;
	}
	cout << ((r >= 2e9) ? -1 : (r + 1)) << endl;
	return 0;
}
posted @ 2020-09-25 21:55  Imakf  阅读(326)  评论(0编辑  收藏  举报