zoukankan      html  css  js  c++  java
  • [笔记] 2-SAT

    一定要加逆否命题啊

    POJ3678

    基本逻辑。
    p||q=1 p为0,q必为1 !p->q !q->p
    p||q=0 p为0,q必为0 p->!p q->!q
    p&&q=1 p为1,q必为1 !p->p !q->q
    p&&q=0 p为1,q必为0 p->!q q->!p
    p^ q=1 p为0,q必为1 
      		 p为1,q必为0
    p^ q=0 p为0,q必为0 !p->!q(原命题) q->p(逆否命题)
      		 p为1,q必为1 p->q(原命题) !q->!p(逆否命题)
    

    POJ3207

    平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,
    比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。
    给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,
    使这些边都不相交。

    Luogu P3825 [NOI2017]游戏

    先把 (a) 赛道转化为 选 (b) 否则选 (c) ,然后就可以 (2-SAT) 辣。

    枚举每个不确定的赛道,注意我们只用枚举两种即可,因为两种类型的赛道即可包含选所有车的情况。

    (mathcal{O}(2^d(n+m)))

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } const int M=400010,N=200010;
    int n,d,m;
    char s[N],ans[N]; int pos[N];
    int vr[M],nxt[M],fir[N],c[N],dfn[N],low[N],stk[N],cnt,num,top,C;
    bool ins[N];
    inline void add(int u,int v) 
      {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    struct node {int u,v,a,b;}e[N];
    inline void tarjan(int u) {
      dfn[u]=low[u]=++num;
      stk[++top]=u,ins[u]=true;
      for(R i=fir[u];i;i=nxt[i]) { 
        R v=vr[i]; 
        if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
        else if(ins[v]) low[u]=min(low[u],dfn[v]);
      } if(dfn[u]==low[u]) {
        R v; ++C;
        do v=stk[top--],c[v]=C,ins[v]=false; while(u!=v);
      }
    }
    inline bool ck() {
      for(R i=1;i<=2*n;++i) if(!dfn[i]) tarjan(i);
      for(R i=1;i<=n;++i) {
        if(c[i]==c[i+n]) return false;
        if(c[i]<c[i+n]) ans[i]=(s[i]=='A')?'B':'A';
        else ans[i]=(s[i]=='C')?'B':'C';
      }
      for(R i=1;i<=n;++i) putchar(ans[i]);
      return true;
    }
    inline void main() {
      n=g(),d=g();
      scanf("%s",s+1);
      for(R i=1,t=0;i<=n;++i) {
        s[i]-=32;
        if(s[i]=='X') pos[t++]=i;
      } m=g();
      for(R i=1;i<=m;++i) 
        e[i].u=g(),e[i].a=getchar(),
        e[i].v=g(),e[i].b=getchar();
      for(R S=0,lim=1<<d,t1,t2;S<=lim;++S) {
        memset(fir,0,sizeof fir),cnt=C=top=0;
        memset(dfn,0,sizeof dfn),
        memset(low,0,sizeof low),
        memset(ins,0,sizeof ins),
        memset(low,0,sizeof low);
        for(R i=0;i<d;++i) s[pos[i]]=(S>>i&1)?'A':'B';
        for(R i=1;i<=m;++i) {
          if(e[i].a==s[e[i].u]) continue;
          if(e[i].b==s[e[i].v]) {
            if(e[i].a=='C'||(e[i].a=='B'&&s[e[i].u]=='C')) 
              add(e[i].u+n,e[i].u); //选第二组的
            else add(e[i].u,e[i].u+n);
            continue;
          }
          t1=(e[i].a=='C'||(e[i].a=='B'&&s[e[i].u]=='C'))*n;
          t2=(e[i].b=='C'||(e[i].b=='B'&&s[e[i].v]=='C'))*n;
          add(e[i].u+t1,e[i].v+t2);
          add(e[i].v-t2+n,e[i].u-t1+n);
        } if(ck()) return ;
      } printf("-1"); 
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2020.01.17

  • 相关阅读:
    docker快速部署DNS,实现快速上线
    图解CentOS系统启动流程
    MySQL/MariaDB读写分离配置
    分享使用PHP开发留言板
    LNMP+Redis架构部署
    Mysql/Mariadb主从复制
    记一次Ubuntu19无法安装docker源
    Tomcat部署项目的三个方法
    Ubuntu部署Tomcat Web服务
    Linux简单检查服务运行脚本
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12204724.html
Copyright © 2011-2022 走看看