BZOJ 1997: [Hnoi2010]Planar 2-SAT

$ \rightarrow $ 戳我进BZOJ原题

[Hnoi2010]Planar

Time Limit: 10 Sec Memory Limit: 64 MB
  ### Description

pic1

 

Input

pic2

 

Output

pic3

 

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

 

Source

Day1
 

题目大意

  • 给定一张无向图以及图中的一个哈密顿回路,判断无向图是否为平面图

  • $ n \le 200.m \le 1000 $
     

题解

  • 除去哈密顿回路( $ n $ 个点的环)之外,每条边有环内、环外两个赋值

  • 若两条边对应环上的区间有重叠,则不能同时在环内或者环外

  • 产生4个条件“若 $ x $ 则 $ y' $ ” “若 $ x' $ 则 $ y $ ” “ 若 $ y $ 则 $ x' $ ” “ 若 $ y' $ 则 $ x $ ”

  • 按照 $ 2-SAT $ 模型求解即可
     

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
#define M 10005
#define N 2005
 
struct edge{ int v,nxt; }e[N<<8];
int head[N],tot;
void add(int u,int v){
    e[++tot].v=v; e[tot].nxt=head[u]; head[u]=tot;
}
 
int n,m,T,u[M],v[M],c[N],pos[N];
stack<int>s;
int dfn[N],low[N],bel[N],tim,scc,cnt;
bool vis[N];
 
void tarjan(int u){
    dfn[u]=low[u]=++tim; s.push(u); vis[u]=1;
    for(int i=head[u];i;i=e[i].nxt)
        if(!dfn[e[i].v]){
            tarjan(e[i].v);
            low[u]=min(low[u],low[e[i].v]);
        } else if(vis[e[i].v])
            low[u]=min(low[u],dfn[e[i].v]);
    if(dfn[u]==low[u]){
        ++scc; 
        do{
            u=s.top(); s.pop(); vis[u]=0;
            bel[u]=scc;
        }while(dfn[u]!=low[u]); }
}
inline bool judge(){
    for(int i=1;i<=cnt;++i)
        if(bel[2*i]==bel[2*i-1]) return 0;
    return 1;
}
inline void init(){
    memset(head,0,sizeof(head));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    cnt=tot=tim=scc=0;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;++i) scanf("%d %d",&u[i],&v[i]);
        for(int i=1;i<=n;++i) scanf("%d",&c[i]);
        if(m>3*n-6){ puts("NO"); continue; }
        init();
        for(int i=1;i<=n;++i) pos[c[i]]=i;
        for(int i=1;i<=m;++i){
            v[i]=pos[v[i]]; u[i]=pos[u[i]];
            if(u[i]>v[i]) swap(u[i],v[i]);
            if(v[i]-u[i]==1||(v[i]==n&&u[i]==1)) continue;
            u[++cnt]=u[i]; v[cnt]=v[i]; 
        }
        for(int i=1;i<=cnt;++i)
            for(int j=i+1;j<=cnt;++j)
                if((u[i]<u[j]&&u[j]<v[i]&&v[i]<v[j])||(u[j]<u[i]&&u[i]<v[j]&&v[j]<v[i])){
                    add(2*i-1,2*j);
                    add(2*i,2*j-1);
                    add(2*j-1,2*i);
                    add(2*j,2*i-1);
                }
        for(int i=1;i<=2*cnt;++i) if(!dfn[i]) tarjan(i);
        if(judge()) puts("YES");
        else puts("NO");
    }
    return 0;
}
posted @ 2018-09-06 08:43  potrem  阅读(182)  评论(0编辑  收藏  举报