首先,如果没有这个平面的限制,考虑不断插入一对点,将与这两点连线有交的线从左到右,依次“移动”到左端点边上,因此一定是可行的
但当存在界限后,对于两个端点都在边界上的点对(一个端点在边界上还是可以用同样的构造),需要判断是否存在合法解:
如果将整个边界看作一个环,若存在两个点对$i$和$j$满足以$ijij$的顺序,那么一定不合法
同时,若不存在这样的关系,通过上述构造,先练两个端点不都在边界上的点对,再连都在边界上的点对,一定可行
考虑如何判定,由于这样的点对从任意一个点开始都是这样的形式,因此从某一点出发,维护一个栈表示当前还没有匹配的点,若当前点已经被插入栈中,且不为栈顶则无解,否则删除栈顶即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define y1 y11 5 vector<int>v; 6 vector<pair<int,int> >vv[4]; 7 stack<int>st; 8 int r,c,n,x1,y1,x2,y2,vis[N]; 9 bool pd(int x,int y){ 10 return ((!x)||(y==c)||(x==r)||(!y)); 11 } 12 void push(int x,int y,int k){ 13 if (!x)vv[0].push_back(make_pair(y,k)); 14 else{ 15 if (y==c)vv[1].push_back(make_pair(x,k)); 16 else{ 17 if (x==r)vv[2].push_back(make_pair(y,k)); 18 else{ 19 if (!y)vv[3].push_back(make_pair(x,k)); 20 } 21 } 22 } 23 } 24 int main(){ 25 scanf("%d%d%d",&r,&c,&n); 26 for(int i=1;i<=n;i++){ 27 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 28 if ((pd(x1,y1))&&(pd(x2,y2))){ 29 push(x1,y1,i); 30 push(x2,y2,i); 31 } 32 } 33 for(int i=0;i<4;i++)sort(vv[i].begin(),vv[i].end()); 34 for(int i=0;i<4;i++) 35 if (i<2) 36 for(int j=0;j<vv[i].size();j++)v.push_back(vv[i][j].second); 37 else 38 for(int j=vv[i].size()-1;j>=0;j--)v.push_back(vv[i][j].second); 39 for(int i=0;i<v.size();i++) 40 if (!vis[v[i]]){ 41 vis[v[i]]=1; 42 st.push(v[i]); 43 } 44 else{ 45 if (st.top()!=v[i]){ 46 printf("NO"); 47 return 0; 48 } 49 st.pop(); 50 } 51 printf("YES"); 52 }