[atARC076E]Connected

首先,如果没有这个平面的限制,考虑不断插入一对点,将与这两点连线有交的线从左到右,依次“移动”到左端点边上,因此一定是可行的

但当存在界限后,对于两个端点都在边界上的点对(一个端点在边界上还是可以用同样的构造),需要判断是否存在合法解:

如果将整个边界看作一个环,若存在两个点对$i$和$j$满足以$ijij$的顺序,那么一定不合法

同时,若不存在这样的关系,通过上述构造,先练两个端点不都在边界上的点对,再连都在边界上的点对,一定可行

考虑如何判定,由于这样的点对从任意一个点开始都是这样的形式,因此从某一点出发,维护一个栈表示当前还没有匹配的点,若当前点已经被插入栈中,且不为栈顶则无解,否则删除栈顶即可

 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 }
View Code

 

posted @ 2021-01-08 19:18  PYWBKTDA  阅读(89)  评论(0编辑  收藏  举报