问题
https://vjudge.net/problem/UVA-11106
给出n个坐标都是整数的顶点,连接成一个多边形,两点之间的边必须水平或者竖直的,每一个顶点都是一条水平边和一条竖直边的端点,输出这个多边形的周长。
分析
同一横坐标的点必须为偶数个,如果只有奇数个,那么会有一个点无法连接一条横向边,同理,同一纵坐标的点一定有偶数个。横坐标相同的两个相邻点一定连接,同理,纵坐标相邻的两个点一定相邻。
限制:所有的点必须连成一个环,边之间不能交叉。
用并查集检测所有的边是否相连(相连那么一定会联成一个环)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=100000+5;
int a,b,n,kase;
map<int,vector<pair<int,int>>> mx,my;
int fa[maxn];
inline int getFa(int x){
if(x==fa[x]) return x;
return fa[x]=getFa(fa[x]);
}
inline int cal(vector<pair<int,int>> &vi){
int t=0,a,b;
for(int i=1;i<vi.size();i+=2){
t+=vi[i].first-vi[i-1].first;
a=getFa(vi[i-1].second);
b=getFa(vi[i].second);
if(a!=b) fa[b]=a;
}
return t;
}
bool check(){
int t=getFa(0);
for(int i=1;i<n;++i){
if(getFa(i)!=t) return false;
}
return true;
}
//判断是否相交
bool intersection(){
for(auto &iter:my){
vector<pair<int,int>> &vi=iter.second;
int y=iter.first;
for(int i=1;i<vi.size();i+=2){
int x1=vi[i-1].first,x2=vi[i].first;
auto iter2=mx.upper_bound(x1);
while(iter2!=mx.end() && (iter2->first<x2)){
vector<pair<int,int>> &vi2=iter2->second;
for(int j=1;j<vi2.size();j+=2){
if(vi2[j-1].first<y && y<vi2[j].first)
return true;
}
++iter2;
}
}
}
return false;
}
int main(void){
scanf("%d",&kase);
while(kase--){
mx.clear();
my.clear();
scanf("%d",&n);
for(int i=0;i<n;++i){
scanf("%d%d",&a,&b);
mx[a].push_back(make_pair(b,i));
my[b].push_back(make_pair(a,i));
fa[i]=i;
}
bool flag=false;
int ans=0;
for(auto &iter:mx){
if(iter.second.size()%2){
flag=true;
break;
}else{
sort(iter.second.begin(),iter.second.end());
ans+=cal(iter.second);
}
}
if(flag){
printf("-1\n");
continue;
}
for(auto &iter:my){
if(iter.second.size()%2){
flag=true;
break;
}else{
sort(iter.second.begin(),iter.second.end());
ans+=cal(iter.second);
}
}
if(flag){
printf("-1\n");
continue;
}
if(!check() || intersection()){
printf("-1\n");
continue;
}
printf("%d\n",ans);
}
return 0;
}
实际上,去掉测试边相交的函数 intersection()也能过去。