bzoj 1997 判斷是否爲平面圖

#include <bits/stdc++.h>
using namespace std;
namespace SAT{
    const int maxn = 20005;
    const int maxm = 5000005;
    int n;
    int he[maxn],ver[maxm],ne[maxm],tot;
    int dfn[maxn],low[maxn],c[maxn],st[maxn],top,tim,color;
    vector<int> bcc[maxn];
    void init(int _n){
        n = _n;
        for( int i = 0; i < 2*n;i ++ ){
            he[i] = 0;
            dfn[i] = 0;
            c[i] = 0;
            bcc[i].clear();
        }
        tim = top = color = 0;
        tot = 1;
    }
    void add( int x,int y ){
        ver[++tot] = y;
        ne[tot] = he[x];
        he[x] = tot;
    }
    void tarjan( int x ){
        st[++top] = x;
        dfn[x] = low[x] = ++tim;
        for( int cure = he[x]; cure; cure = ne[cure] ){
            int y = ver[cure];
            if( !dfn[y] ){
                tarjan(y);
                low[x] = min( low[x],low[y] );
            }else if( !c[y] ){
                low[x] = min( low[x],dfn[y] );
            }
        }
        if( low[x] == dfn[x] ){
            int cur;
            color++;
            do{
                cur = st[top--];
                c[cur] = color;
                bcc[color].push_back( cur );
            }while( cur != x );
        }
    }
    void add_clause( int x,int p,int y,int q ){
        add( x+p*n,y+(q^1)*n );
        add( y+q*n,x+(p^1 )*n );
    }
    bool solve(){
        for( int i = 0; i < 2 * n;i++ ){
            if( dfn[i] ) continue;
            tarjan(i);
        }
        for( int i = 0; i < n;i ++ ){
            if( c[i] == c[i+n] ) return false;
        }
        return true;
    }
};
const int maxm = 10005;
const int maxn = 505;
int u[maxm],v[maxm],a[maxn],pos[maxn];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
       int n,m;
       scanf("%d%d",&n,&m);
       for( int i = 0;i < m;i++ ){
           scanf("%d%d",&u[i],&v[i]);
       }
       SAT::init(m);
       for( int i = 1;i <= n;i++ )scanf("%d",&a[i]);
       if( m > 3*n-6 ){
           puts("NO");
           continue;
       }
       for( int i = 1;i <= n;i++ ) pos[a[i]] = i;
       int top = 0;
       for( int i = 0;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[++top] = u[i],v[top] = v[i];
       }
       for( int i = 0;i < m;i++ ){
           for( int j = i+1;j < m;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]) ){
                   SAT::add_clause( i,0,j,0 );
                   SAT::add_clause(i,1,j,1);
               }
           }
       }
       top = 0;
       bool flag = SAT::solve();
       if(flag){
           puts("YES");
       }else{
           puts("NO");
       }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章