D39 2-SAT P3209 [HNOI2010] 平面图判定

视频链接:D39 2-SAT P3209 [HNOI2010] 平面图判定_哔哩哔哩_bilibili

 

 

 

图论(十三)——平面图和对偶图_图论(十三)——平面图和对偶图-CSDN博客

P3209 [HNOI2010] 平面图判定 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=10005;
int n,m,T,x[N],y[N],id[N];
int dfn[N],low[N],stk[N],scc[N],tim,top,cnt;
int head[N],idx;
struct Edge{int to,ne;}e[1000005];

void add(int a,int b){
  e[++idx].to=b;
  e[idx].ne=head[a];
  head[a]=idx;
}
void tarjan(int x){
  dfn[x]=low[x]=++tim;
  stk[++top]=x;
  for(int i=head[x];i;i=e[i].ne){
    int y=e[i].to;
    if(!dfn[y]){ //若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(!scc[y]) //若y已访问且未处理
      low[x]=min(low[x],dfn[y]);
  }
  
  if(low[x]==dfn[x]){ //若x是SCC的根
    ++cnt;
    for(int y=-1;y!=x;)
      scc[y=stk[top--]]=cnt;
  }
}
int main(){
  scanf("%d",&T);
  while(T--){
    scanf("%d%d",&n,&m);
    tim=top=cnt=idx=0;
    for(int i=1;i<=N;i++)
      head[i]=dfn[i]=stk[i]=scc[i]=0;
      
    for(int i=1;i<=m;i++)
      scanf("%d%d",&x[i],&y[i]);
    for(int i=1,x;i<=n;i++)
      scanf("%d",&x), id[x]=i; //保存点的序号
    
    int flag=0;
    if(m>3*n-6) flag=1; //无解
    else{
      for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++){
          int xi=id[x[i]],yi=id[y[i]],xj=id[x[j]],yj=id[y[j]];
          if(xi>yi) swap(xi,yi); if(xj>yj) swap(xj,yj);
          if(xi<xj&&xj<yi&&yi<yj||xj<xi&&xi<yj&&yj<yi){
            add(i,j+m); //i内j外
            add(i+m,j); //i外j内
          }        
        }
  
      for(int i=1;i<=2*m;i++) if(!dfn[i]) tarjan(i);
      for(int i=1;i<=m;i++)
        if(scc[i]==scc[i+m]) flag=1; //无解
    }
    flag?puts("NO"):puts("YES");
  }
}

 

posted @ 2024-08-06 16:50  董晓  阅读(107)  评论(0编辑  收藏  举报