有很多个点,最多一万个,告诉你它们的坐标。现在需要构造一条闭合线。
这个闭合线满足以下六点:
1必须是闭合的。
2必须用到所有的点。
3构造的线段之间若成角,则必须是90度。
4构造的边必须与x或y轴平行。
5构造的线段之间不存在交错和重复的情况。
6最后形成的闭合线长度必须要是所有可能中最短的。
首先根据题意处理出线段
横坐标相等的,按纵坐标从小到大排序,
第一个点与第二个点相连,第三个与第四个相连。。。
纵坐标相等的,按横坐标从小到大排序,
第一个点与第二个点相连,第三个与第四个相连。。。
O(N∗logN)
最后判断连通与自交的情况,
连通用并查集
O(N)
,
自交用暴力(^_^),
O(N2)
,然而常数较小
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
const int MAXN = 10005;
int n;
int fa[MAXN] = {0};
struct node{int x,y,i;}map[MAXN] = {0} , map0[MAXN] ={0};
struct line{int i1,i2;}mpr[MAXN] = {0}, mpc[MAXN] = {0};
int rl = 0 , cl = 0;
bool cmpr(const node &a,const node &b){return ((a.y<b.y)||(a.y == b.y && a.x<b.x));}
bool cmpc(const node &a,const node &b){return ((a.x<b.x)||(a.x == b.x && a.y<b.y));}
bool row()
{
std::sort(map + 1, map + n +1 , cmpr);
for(int i = 2; i <= n ; i += 2)
{
int j = i - 1;
if(map[i].y == map[j].y)
{
++rl;
mpr[rl].i1 = map[j].i;
mpr[rl].i2 = map[i].i;
}
else return false;
}
return true;
}
bool col()
{
std::sort(map + 1, map + n +1 , cmpc);
for(int i = 2; i <= n ; i += 2)
{
int j = i - 1;
if(map[i].x == map[j].x)
{
++cl;
mpc[cl].i1 = map[j].i;
mpc[cl].i2 = map[i].i;
}
else return false;
}
return true;
}
int find_fa(int x)
{
if(x == fa[x])return x;
else
{
fa[x] = find_fa(fa[x]);
return fa[x];
}
}
bool connect()
{
for(int i = 1 ; i <= rl; i++)
{
int u = find_fa(mpr[i].i1) , v = find_fa(mpr[i].i2);
fa[std::max(u,v)] = std::min(u,v);
}
for(int i = 1 ; i <= cl ;i++)
{
int u = find_fa(mpc[i].i1) , v = find_fa(mpc[i].i2);
fa[std::max(u,v)] = std::min(u,v);
}
for(int i = 1; i <= n; i++)
{
find_fa(i);
if(!(fa[i] == 1))return false;
}
return true;
}
bool crossed()
{
for(int i = 1 ; i <= rl; i++)
for(int j = 1 ;j <= cl ; j++)
{
int a = mpr[i].i1, b = mpr[i].i2, c = mpc[j].i1, d = mpc[j].i2;
if(map0[a].x < map0[c].x && map0[d].x < map0[b].x)
if(map0[c].y < map0[a].y && map0[b].y < map0[d].y)
return true;
}
return false;
}
int count()
{
int ret = 0;
for(int i = 1 ; i <= rl; i++)ret += (map0[mpr[i].i2].x - map0[mpr[i].i1].x);
for(int i = 1 ; i <= cl; i++)ret += (map0[mpc[i].i2].y - map0[mpc[i].i1].y);
return ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu128.in","r",stdin);
freopen("sgu128.out","w",stdout);
#endif
scanf("%d",&n);
for(int i = 1; i <= n;i++)
{
scanf("%d%d",&map[i].x, &map[i].y);
map[i].i = i , fa[i] = i;
map0[i] = map[i];
}
if(((n&1)==0) &&row() && col() && connect() && (!crossed()))
printf("%d",count());
else
printf("0");
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
}