[bzoj1997][Hnoi2010] plane graph determination -- 2-SAT + plane graph theorem

Posted by kid85 on Thu, 02 Jan 2020 08:15:09 +0100

Main idea:

Given a graph with Hamiltonian circuit, we can find out whether it is a plane graph or not.

Train of thought:

Since there are Hamiltonian circuits, we can regard the outside and inside of the ring as two different regions, and then if there are not edges on the ring that intersect, we can't be in or out of the ring at the same time. It can then be transformed into a 2-SAT model.
But it is found that if enumeration is used to connect edges, it is likely to TLE. At this time, we need to use a theorem of planar graph, that is, the number of edges of any planar graph is no more than 3*n-6. As for the proof, I don't know..
And then just enumerate the 2-SAT running on the edge.

#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a;i<=b;++i)
#define pii pair<int,int>
#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<<E[i].fi<<" "<<E[i].se<<endl;
    }
}

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<<i<<" "<<j<<endl;//" "<<E[i].fi<<" "<<E[i].se<<" "<<E[j].fi<<" "<<E[j].se<<endl;
        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<<i<<" "<<j+m<<endl;
        //cout<<j<<" "<<i+m<<endl;
    }
    //cout<<"--------------------"<<endl;
}

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<<p<<" ";
            bel[p]=cnt_scc;
        }
        //cout<<endl;
    }
}

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;
}