• 洛谷P3209 [HNOI2010]平面图判定(2-SAT)


    传送门

    看到哈密顿回路就被吓傻了……结果没有好好考虑性质……

    首先,平面图有个性质:边数小于等于$3n-6$(我也不知道为啥),边数大于这个的直接pass

    然后考虑原图,先把哈密顿回路单独摘出来,就是一个环。对于每一条不在哈密顿回路上的边,有两种可能,一种是在环内,一种是在环外

    我们用点来表示每一条边,把每一个点拆成两个分别表示这条边是在环内还是环外。对于两条边$i,j$,如果他们同时在环外或环内会交叉,那么就相当于有了约束条件,转化成一个2-SAT问题即可

    至于连边,我们设$i$表示在环内,$i+m$表示在环外,如果$i,j$同在环内或环外会相交,那么连边$(i,j+m),(i+m,j),(j,i+m),(j+m,i)$,即他们永远不能同时在环内或环外

    至于如果判断是否会相交,我们可以把环拆开,然后判断同在一侧是否会相交即可

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #define mem(a) (memset(a,0,sizeof(a)))
     6 #define swap(x,y) (x^=y^=x^=y)
     7 using namespace std;
     8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     9 char buf[1<<21],*p1=buf,*p2=buf;
    10 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    11 inline int read(){
    12     #define num ch-'0'
    13     char ch;bool flag=0;int res;
    14     while(!isdigit(ch=getc()))
    15     (ch=='-')&&(flag=true);
    16     for(res=num;isdigit(ch=getc());res=res*10+num);
    17     (flag)&&(res=-res);
    18     #undef num
    19     return res;
    20 }
    21 const int N=2e4+5,M=1e5+5;
    22 int head[N],Next[M],ver[M],tot;
    23 inline void add(int u,int v){
    24     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
    25 }
    26 int dfn[N],low[N],bl[N],st[N],num,cnt,top,n,m,k;
    27 void tarjan(int u){
    28     dfn[u]=low[u]=++num,st[++top]=u;
    29     for(int i=head[u];i;i=Next[i]){
    30         int v=ver[i];
    31         if(!dfn[v]) tarjan(v),cmin(low[u],low[v]);
    32         else if(!bl[v]) cmin(low[u],dfn[v]);
    33     }
    34     if(low[u]==dfn[u]) for(++cnt;st[top+1]!=u;--top) bl[st[top]]=cnt;
    35 }
    36 inline bool check(){
    37     for(int i=1,l=m<<1;i<=l;++i) if(!dfn[i]) tarjan(i);
    38     for(int i=1;i<=m;++i)
    39     if(bl[i]==bl[i+m]) return false;
    40     return true;
    41 }
    42 int rev[205],cir[205][205],E[205],eu[N],ev[N];
    43 void clear(){
    44     mem(head),mem(dfn),mem(low),mem(bl),mem(st),mem(cir);
    45     num=cnt=top=tot=0;
    46 }
    47 void solve(){
    48     clear();
    49     n=read(),m=read(),k=0;
    50     for(int i=1;i<=m;++i){
    51         eu[i]=read(),ev[i]=read();
    52         if(eu[i]>ev[i]) swap(eu[i],ev[i]);
    53     }
    54     for(int i=1;i<=n;++i){
    55         rev[E[i]=read()]=i;
    56         if(i>1){
    57             int u=E[i-1],v=E[i];
    58             u<v?cir[u][v]=1:cir[v][u]=1;
    59         }
    60     }
    61     if(m>3*n-6) return (void)(puts("NO"));
    62     for(int i=1;i<=m;++i)
    63     if(!cir[eu[i]][ev[i]]) eu[++k]=eu[i],ev[k]=ev[i];
    64     m=k;
    65     for(int i=1;i<m;++i)
    66     for(int j=i+1;j<=m;++j){
    67         int u=rev[eu[i]],v=rev[ev[i]],x=rev[eu[j]],y=rev[ev[j]];
    68         if(u>v) swap(u,v);if(x>y) swap(x,y);
    69         if((u<x&&v>x&&v<y)||(u>x&&u<y&&v>y)){
    70             add(i,j+m),add(j,i+m),add(i+m,j),add(j+m,i);
    71         }
    72     }
    73     puts(check()?"YES":"NO");
    74 }
    75 int main(){
    76 //    freopen("testdata.in","r",stdin);
    77     int T=read();
    78     while(T--) solve();
    79     return 0;
    80 }
  • 相关阅读:
    【nodejs】vscode添加nodejs调试功能
    【nodejs】简单的httpserver
    windows下,强制关闭某端口号的进程
    git 客户端用户名密码配置
    【shell】变量替换
    aksk鉴权
    vue学习笔记-第一课
    好未来上海一面电面
    20190325面试题记录(中级java)
    IT帮-三月份-职业规划主题笔记
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9786066.html
Copyright © 2020-2023  润新知