BZOJ1997 [Hnoi2010]Planar (2-sat)

题意:给你一个哈密顿图,判断是不是平面图

思路:先找出哈密顿图来。哈密顿回路可以看成一个环,把边集划分成两个集合,一个在环内,一个在外。如果有两条相交边在环内,则一定不是平面图,所以默认两条相交边,转化成2——sat,两条边不能同时在内或外,注意双向加边。(以边来转化成两倍)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<queue>
  5 #include<stack>
  6 #include<bits/stdc++.h>
  7 using namespace std;
  8 #define LL long long
  9 #define clc(a,b) memset(a,b,sizeof(a))
 10 const int maxn = 2000 + 10;
 11 int r(){
 12     int x=0,f=1;char ch=getchar();
 13     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 14     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 15     return x*f;
 16 }
 17 int T,n,m,ind,top,cnt,scc;
 18 int u[10005],v[10005];
 19 int c[2010],pos[2005];
 20 int last[2005],dfn[2005],low[2005],q[2005],bl[2005];
 21 bool inq[2005];
 22
 23 struct edge{
 24     int to,next;
 25 }e[1000005];
 26
 27 void add(int u,int v){
 28     e[++cnt].to=v;
 29     e[cnt].next=last[u];
 30     last[u]=cnt;
 31 }
 32
 33 void tarjan(int x){
 34     inq[x]=1;q[++top]=x;
 35     low[x]=dfn[x]=++ind;
 36     for(int i=last[x];i;i=e[i].next)
 37         if(!dfn[e[i].to])
 38             tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]);
 39         else if(inq[e[i].to])
 40             low[x]=min(low[x],dfn[e[i].to]);
 41     int now=-1;
 42     if(low[x]==dfn[x])
 43     {
 44         scc++;
 45         while(now!=x)
 46         {
 47             now=q[top--];inq[now]=0;
 48             bl[now]=scc;
 49         }
 50     }
 51 }
 52
 53 bool jude(){
 54     for(int i=1;i<=m;i++){
 55         if(bl[i*2]==bl[i*2-1])
 56             return false;
 57     }
 58  return true;
 59 }
 60 int main(){
 61     T=r();
 62     while(T--){
 63           n=r(),m=r();
 64           for(int i=1;i<=m;i++){
 65             u[i]=r();v[i]=r();
 66           }
 67           clc(last,0);
 68           cnt=0;
 69           scc=ind=0;
 70           clc(low,0);
 71           clc(dfn,0);
 72           for(int i=1;i<=n;i++)
 73             c[i]=r();
 74         if(m>3*n-6){
 75             printf("NO\n");
 76             continue;
 77         }
 78         for(int i=1;i<=n;i++)
 79             pos[c[i]]=i;
 80         top=0;
 81         for(int i=1;i<=m;i++){
 82             u[i]=pos[u[i]],v[i]=pos[v[i]];
 83             if(u[i]>v[i]) swap(u[i],v[i]);
 84             if(v[i]-u[i]==1||v[i]-u[i]==n-1) continue;
 85             u[++top]=u[i],v[top]=v[i];
 86         }
 87         m=top;
 88         for(int i=1;i<=m;i++){
 89             for(int j=i+1;j<=m;j++){
 90                 if((u[i]<u[j]&&v[i]>u[j]&&v[i]<v[j])||(u[i]>u[j]&&v[j]>u[i]&&v[i]>v[j])){
 91                     add(2*i-1,2*j);
 92                     add(2*i,2*j-1);
 93                     add(2*j-1,2*i);
 94                     add(2*j,2*i-1);
 95                 }
 96             }
 97         }
 98         for(int i=1;i<=2*m;i++){
 99            if(dfn[i]==0){
100             tarjan(i);
101            }
102         }
103         if(jude()) printf("YES\n");
104         else printf("NO\n");
105
106     }
107     return 0;
108 }

时间: 2024-08-16 10:32:19

BZOJ1997 [Hnoi2010]Planar (2-sat)的相关文章

bzoj1997: [Hnoi2010]Planar

2-SAT. 首先有平面图定理 m<=3*n-6,如果不满足这条件肯定不是平面图,直接退出. 然后构成哈密顿回路的边直接忽略. 把哈密顿回路当成一个圆, 如果俩条边交叉(用心去感受),只能一条边在圆内,另一条在圆外. 这个是2-sat的A,B要不同时取,要不同时不取模型. 如果俩个交叉,只能一个在内,一个在外. 和A,B俩者不能同时取有区别,需要注意. 可能存在3个方案(A,B'),(B,A'),(A',B'). 连方案都不要,直接tarjan完就过了. #include<cstdio>

【BZOJ1997】[Hnoi2010]Planar 2-SAT

[BZOJ1997][Hnoi2010]Planar Description Input Output Sample Input 2 6 9 1 4 1 5 1 6 2 4 2 5 2 6 3 4 3 5 3 6 1 4 2 5 3 6 5 5 1 2 2 3 3 4 4 5 5 1 1 2 3 4 5 Sample Output NO YES 题解:跟HDU的某熊猫题一模一样?(然而我并没有写那题的题解~) 本题可以理解为圆上有一些点之间要连线,这些线要么在圆里要么在圆外,问能否让所有的线都不

BZOJ 1997: [Hnoi2010]Planar( 2sat )

平面图中E ≤ V*2-6.. 一个圈上2个点的边可以是在外或者内, 经典的2sat问题.. ------------------------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; #

bzoj 1997: [Hnoi2010]Planar

Description Input Output Sample Input 2 6 9 1 4 1 5 1 6 2 4 2 5 2 6 3 4 3 5 3 6 1 4 2 5 3 6 5 5 1 2 2 3 3 4 4 5 5 1 1 2 3 4 5 Sample Output NO YES HINT Source Day1 考虑题目中给了一个哈密顿回路,那么我们把这个哈密顿回路在草稿纸上画成一个环... 然后考虑还不在环上的边,这些边有两种加入的方法,一是画在环的里面,二是画在环的外面...

[BZOJ 1997][HNOI2010]Planar(2-SAT)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1997 分析: 考虑每条边是在圈子里面还是圈子外面 所以就变成了2-SAT判定问题了= =,于是求SCC,如果一个点对应的2个bool点在一个SCC中就无解了. 当然这样建图好像要TLE…… 然后就要上大杀器了:平面图|E|<=3|V|-6 所以,如果m>3n-6就直接输出NO了

【BZOJ 1997】[Hnoi2010]Planar

Description Input Output 找到哈密尔顿环之后找到不在哈密尔顿环上的边 这些边如果同时在里面相交那他们同时在外面也相交,所以只能一外一内,这就变成了2-SAT,判一下就好了 平面图性质 边数<=3*n-6 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 int T,n,m,timer,top,cnt,scc; 6 int

[BZOJ1997][HNOI2010] 平面图判定

Description Input Output 是的..BZOJ样例都没给. 题解(from 出题人): 如果只考虑简单的平面图判定,这个问题是非常不好做的. 但是题目中有一个条件——这张图存在一条哈密顿回路. 我们把哈密顿回路在平面上画成一个圆.仔细观察一下. 每条边如果画在圆内都是一条弦,那如果弦在圆内相交怎么办?把另一条弦翻出去.能不能两条弦都翻出去呢?不能,因为如果两条边在圆内相交,那么它们在圆外也会相交.那我们是不是就相当于就多了一个条件:这两条边不能同时在一个域内. 所以,这张图中

联赛之前的题表(已完成)汇总(可能有遗漏)

联赛之前的搞搞(其实是懒得分类) 博弈论 poj3537 poj1704 hdu5996两个插头 HDU1693 Eat the Trees COGS1283. [HNOI2004] 邮递员kdtree板子1941: [Sdoi2010]Hide and Seek旋转卡壳 pj2187凸包 cogs896 bzoj2829 信用卡凸包莫比乌斯反演基础 bzoj 4173 zhao gui lv bzoj 3529 mobiwus bzoj 4407 mobiwus bzoj 2818 mobiw

[HNOI2010] 平面图判定 planar

标签:二分图判定.题解: 首先可以把题目中给你的那个环给画出来,这样就可以发现对于任意一个图来说,如果两条边要相交,就不能让他们相交,那么这两条边就要一条在里面一条在外面,如果把环画成一条链,那么就是一条在下面,一条在上面.于是我们想到对于边,O(n2)的枚举,判断是否相交即可,如果相交的话,就要连一条边,到时候判断这一个图(把原图边看成新图的点)是不是二分图即可,简单的二分图染色判定即可. 当然了O(n2)对于10000条边来说,因为有多组数据,会被卡掉,那么我们就要想办法,点这么少,边这么多