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

 

posted @ 2016-04-13 00:43  yyblues  阅读(266)  评论(0编辑  收藏  举报