AtCoder Regular Contest 076E Coneected?

题意

给出一个矩形区域和上面的m对整点,要求在矩形区域内画m条互不相交的线(可以是曲线)分别把m对点连接起来.只需要输出能不能做到.

分析

假设我们已经画了一条线.因为在这个题中有用的是平面区域之间的相对位置,那么这条线我们可以随便拉长,缩短,点的位置也可以移动而不影响结果.因此,如果一对点都不在矩形区域的边界上,我们可以把它们之间连线然后把这两个点之间的线缩短,把一个点移动到另一个点的位置上.如果有一个点在边界上,另一个点不在边界上,那么可以连线之后把不在边界上的点移动到边界上.
可以,这很拓扑
因此我们可以断言:只有两个点都在边界上的点会产生矛盾.现在我们可以把边界看成一个环,上面有m对点,要求在环的内部画线分别把m对点连接起来.那么给所有点逆时针排序后,如果有两对点(A1,A2)和(B1,B2)是A1,B1,A2,B2的顺序,那么无解.如果有解的话,任意两对点在环上所占的区间要么相互包含,要么互不相交.那么这是一个类似括号序列的东西,拿栈扫一遍就可以了.

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100005;
int R,C,N;
struct point{
  int x,y,num;
  void read(){
    scanf("%d%d",&x,&y);
  }
  bool onedge(){
    if(x==0||y==0||x==R||y==C)return true;
    else return false;
  }
  int typ()const{
    if(x==0)return 1;
    else if(y==0)return 2;
    else if(x==R)return 3;
    else return 4;
  }
  bool operator <(const point &B)const{
    int t1=typ(),t2=B.typ();
    if(t1!=t2)return t1<t2;
    else if(t1==1)return y>B.y;
    else if(t1==2)return x<B.x;
    else if(t1==3)return y<B.y;
    else return x>B.x;
  }
}P[maxn][2];
point P2[maxn*2];int tot=0;
int stk[maxn*2],top=0;
int main(){
  scanf("%d%d%d",&R,&C,&N);
  for(int i=1;i<=N;++i){
    P[i][0].read();P[i][1].read();P[i][0].num=P[i][1].num=i;
    if((P[i][0].onedge())&&(P[i][1].onedge())){
      P2[++tot]=P[i][0];P2[++tot]=P[i][1];
    }
  }
  sort(P2+1,P2+tot+1);
  for(int i=1;i<=tot;++i){
    if(top&&stk[top-1]==P2[i].num)--top;
    else stk[top++]=P2[i].num;
  }
  if(top)printf("NO
");
  else printf("YES
");
  return 0;
}

原文地址:https://www.cnblogs.com/liu-runda/p/7099863.html