[bzoj1997][Hnoi2010]平面图判定——2-SAT+平面图定理

题目大意:

给定一个带有哈密顿回路的图,求此图是否为平面图。

思路:

既然有哈密顿回路,则可以把环外和环内看成两个不同的区域,然后如果有不是环上的边相交的话就不能同时在环内或者环外。然后就可以转化为2-SAT模型。
但是发现如果枚举去连边的话显然很可能会TLE。这个时候要用到平面图的一个定理,即任意一个平面图的边的个数不大于3*n-6,至于证明我就不知道了。。
然后就直接枚举连边跑2-SAT就好了。

#include

#define REP(i,a,b) for(int i=a;i<=b;++i)
#define pii pair
#define fi first
#define se second
#define mk make_pair
typedef long long ll;

using namespace std;

void File(){
    freopen("bzoj1997.in","r",stdin);
    freopen("bzoj1997.out","w",stdout);
}

template<typename T>void read(T &_){
    T __=0,mul=1; char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')mul=-1;
        ch=getchar();
    }
    while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
    _=__*mul;
}

const int maxn=200+10;
const int maxm=1e4+10;
int T,n,m,a[maxn],pos[maxn];
pii E[maxm];
vector<int>G[maxn*6];

void init(){
    read(n); read(m);
    int u,v;
    REP(i,1,m)read(u),read(v),E[i]=mk(u,v);
    REP(i,1,n)read(a[i]),pos[a[i]]=i;
    REP(i,1,m){
        E[i].fi=pos[E[i].fi]; E[i].se=pos[E[i].se];
        if(E[i].fi>E[i].se)swap(E[i].fi,E[i].se);
        //cout<
    }
}

void build_map(){
    REP(i,1,m*2)G[i].clear();
    REP(i,1,m)REP(j,i+1,m){
        if(E[i].fi<=E[j].fi && E[i].se>=E[j].se)continue;
        if(E[i].fi>=E[j].fi && E[i].se<=E[j].se)continue;
        if(E[i].se<=E[j].fi || E[j].se<=E[i].fi)continue;
        //cout<
        G[i].push_back(j+m);
        G[j].push_back(i+m);
        G[i+m].push_back(j);
        G[j+m].push_back(i);
        //cout<
        //cout<
    }
    //cout<<"--------------------"<
}

int low[maxm*6],dfn[maxm*6],cnt_dfn,cnt_scc,bel[maxm*6];
stack<int>stk;

void tarjan(int u){
    low[u]=dfn[u]=++cnt_dfn;
    stk.push(u);
    for(int sz=G[u].size()-1,i=0;i<=sz;++i){
        int v=G[u][i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!bel[v])low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        ++cnt_scc;
        for(int p=0;p!=u;stk.pop()){
            p=stk.top();
            //cout<
            bel[p]=cnt_scc;
        }
        //cout<
    }
}

bool work(){
    cnt_dfn=cnt_scc=0;
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(bel,0,sizeof(bel));
    REP(i,1,m*2)if(!dfn[i])
        tarjan(i);
    REP(i,1,m)if(bel[i]==bel[i+m])
        return false;
    return true;
}

int main(){
    File();
    read(T);
    while(T--){
        init();
        if(m>3*n-6){
            puts("NO");
            continue;
        }
        build_map();
        work() ? puts("YES") : puts("NO");
    }
    return 0;
}

你可能感兴趣的:(哈密顿回路,2-SAT)