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

 

// 并查集 O(Tm^2)
#include<bits/stdc++.h>
using namespace std;

int read(){
  int s=0; char c=getchar();
  while(c<'0'||c > '9') c=getchar();
  while('0'<=c && c<='9')s=s*10+(c-'0'),c=getchar();
  return s;
}

const int N=2005;
int T,n,m;
int x[N<<4],y[N<<4],vis[N<<4];
int id[N];
int fa[N<<5];

int find(int x){
  return fa[x]==x?x:fa[x]=find(fa[x]);
}
bool cross(int x1,int x2,int y1,int y2){
  if(x1==x2||y1==y2||x1==y2||x2==y1)return 0;
  if(x1<x2 && y1<y2 && x2<y1)return 1;
  if(x2<x1 && y2<y1 && x1<y2)return 1;
  return 0;
}
bool check(){
  for(int i=1;i<=m<<1;i++)fa[i]=i;
  for(int i=1;i<=m;i++){
    if(vis[i])continue;
    for(int j=1;j<=m;j++){
      if(vis[j])continue;
      if(!cross(x[i],x[j],y[i],y[j]))continue;
      int ii=find(i),jj=find(j);
      if(ii==jj)return 0;
      fa[ii]=find(j+m),
      fa[jj]=find(i+m);
    }
  }
  return 1;
}
int main(){
  T=read();
  while(T--){
    memset(vis,0,sizeof(vis));
    n=read(),m=read();
    for(int i=1;i<=m;i++) x[i]=read(),y[i]=read();
    for(int i=1;i<=n;i++) id[read()]=i;
    if(m>3*n+6){
      puts("NO"); continue;
    }
    for(int i=1,a,b;i<=m;i++){
      a=id[x[i]],b=id[y[i]];
      x[i]=min(a,b),
      y[i]=max(a,b);
    }
    for(int i=1;i<=m;i++)if(y[i]==x[i]+1||(y[i]==n&&x[i]==0))vis[i]=1;
    if(check())puts("YES");
    else puts("NO");
  }
  return 0;
}

 

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