A. Fence Planning

GDUT 2020寒假训练 排位赛二 A

原题链接

题目

原题截图
Farmer John’s N cows, conveniently numbered 1…N (2≤N≤105), have a complex social structure revolving around “moo networks” — smaller groups of cows that communicate within their group but not with other groups. Each cow is situated at a distinct (x,y) location on the 2D map of the farm, and we know that M pairs of cows (1≤M<105) moo at each-other. Two cows that moo at each-other belong to the same moo network.

In an effort to update his farm, Farmer John wants to build a rectangular fence, with its edges parallel to the x and y axes. Farmer John wants to make sure that at least one moo network is completely enclosed by the fence (cows on the boundary of the rectangle count as being enclosed). Please help Farmer John determine the smallest possible perimeter of a fence that satisfies this requirement. It is possible for this fence to have zero width or zero height.

Input
The first line of input contains N and M. The next N lines each contain the x and y coordinates of a cow (nonnegative integers of size at most 108). The next M lines each contain two integers a and b describing a moo connection between cows a and b. Every cow has at least one moo connection, and no connection is repeated in the input.

Output
Please print the smallest perimeter of a fence satisfying Farmer John’s requirements.

样例

input
7 5
0 5
10 5
5 0
5 10
6 7
8 6
8 4
1 2
2 3
3 4
5 6
7 6
output
10

题目大意

有n头牛,每一头牛有一个坐标(10^8以内的非负整数),然后给出m对关系,每一对关系中国包含x和y,表示x和y同属于一个集合,现在要用篱笆将一个集合围住(篱笆为平行于xy轴的矩形,在篱笆边界的牛也算被围住),求篱笆的最小周长。

思路1

并查集
整体思路就是并查集,然后对于每一个集合找到这个集合内x和y轴的最大差值形成一个矩形,遍历每一集合,找到最小矩形就可以了
先初始化并读入点坐标,在建立关系的时候合并同一个集合。
然后对点进行遍历,遍历到每一个点的时候都查找到他所属的集合,更新这个集合的最大x轴和最小x轴 最大y轴和最小y轴。
最后再次遍历每一个点,找到该点的fa[x] == x 也就是集合的老大,计算x轴的最大差值和y轴的最大差值,更新答案。
然后要注意的是,在对点进行第一次遍历的时候fa[x]并不是x所在的集合的老大编号,因为在并查集路径压缩的时候,可能这个点没有被更新到,也就是要再进行一次查询 getfa(x)才是x所在集合的老大
其次,inf=9999999并不大,就是这个坑,从开题到比赛结束,一直到补题对比了其他人写的代码的时候,才发现,是inf的锅。在比赛的时候我的ans=1e5+7 然后ans=min(ans,temp) temp是算出当前集合的篱笆周长的一半,之后就一直卡test2 以为是并查集的锅,但是怎么想都觉得算法没有问题,最后比赛结束WA了4次还没过,心态略崩。
在补题的时候开其他人的代码思路也是并查集,跟我的代码差不多,直到看到有同学写ans=-1,当检测到 ans ==-1的时候将 当前的temp直接赋值给ans 以后ans=min(ans,temp)。我改成这个之后就过了,果然,以后肯定不瞎赋最大值了,0x3f3f3f3f都不敢了。
抱拳

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+7;
const int INF = 0x3f3f3f3f;
struct Point{
	int x,y;
	int max_x,min_x;
	int max_y,min_y;
}p[maxn];
int fa[maxn];
int getfa(int x)
{
	return fa[x]==x? fa[x] :fa[x]=getfa(fa[x]);	
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&p[i].x,&p[i].y);
		p[i].max_x=-INF;
		p[i].max_y=-INF;
		p[i].min_x=INF;
		p[i].min_y=INF;
	}
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
	}
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		int fx=getfa(x);
		int fy=getfa(y);
		if(fx!=fy)
		{
			fa[fx]=fy;
		}
	}
	long minn=-1;
	long temp;
	for(int i=1;i<=n;i++)
	{
		int fx=getfa(i);
		p[fx].max_x=max(p[i].x,p[fx].max_x);
		p[fx].max_y=max(p[i].y,p[fx].max_y);
		p[fx].min_x=min(p[i].x,p[fx].min_x);
		p[fx].min_y=min(p[i].y,p[fx].min_y);
		
	}
	for(int i=1;i<=n;i++)
	{
		
		if(fa[i]==i)
		{
			temp=p[i].max_x-p[i].min_x+p[i].max_y-p[i].min_y;
			if(minn==-1)
				minn=temp;
			else 
				minn=min(minn,temp);
		}
	}
	cout<<minn*2<<endl;
	return 0;
}
发布了21 篇原创文章 · 获赞 1 · 访问量 421

猜你喜欢

转载自blog.csdn.net/xcy2001/article/details/104469639