zoukankan      html  css  js  c++  java
  • LOJ #6036.「雅礼集训 2017 Day4」编码 Trie树上2-sat

    记得之前做过几道2-sat裸体,以及几道2-sat前缀优化建图,这道题使用了前缀树上前缀树优化建图.
    我们暴力建图肯定是n^2级别的,那么我们要是想让边数少点,就得使用一些骚操作.
    我们观察我们的限制条件,不就是选了一个点,那么这个点的前缀都不能选吗(选了一个点,以他为前缀的的点也不能选,这个限制条件可以通过前面那个限制条件体现出来,所以说观察到问题本质是一样的,可以简化我们的问题).那么我们就可以在Trie上建图,使得选择一个点,那么他的前缀点都必须不能选,就可以了.但是对于一个点上有多个点的情况,我们要特殊处理,我的处理方法是,把那些点拽出来作为树点.
    最后说一下,要注意2-sat建图一定要连逆否命题边.
    (感觉自己2-sat好虚啊……)
    语言笔记:
    exit(0),只要你在程序中使用,无论在哪里,直接正常退出,具体情况见http://blog.csdn.net/u010046690/article/details/47105665

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    const int N=500010;
    struct V{
      int to,next;
    }c[N<<6];
    int head[N<<1],t;
    inline void add(int x,int y){
      c[++t].to=y,c[t].next=head[x],head[x]=t;
    }
    char s[N],*begin[N];
    int n,len[N],m;
    int pos[N],temp[N];
    int dfn[N<<1],low[N<<1],belong[N<<1],stack[N<<1],top,num,Ti;
    bool in[N<<1];
    inline void Tarjan(int x){
      dfn[x]=low[x]=++Ti;
      stack[++top]=x;
      in[x]=true;
      register int i;
      for(i=head[x];i;i=c[i].next)
        if(!dfn[c[i].to]){
          Tarjan(c[i].to);
          low[x]=std::min(low[x],low[c[i].to]);
        }else if(in[c[i].to])
          low[x]=std::min(low[x],dfn[c[i].to]);
      if(low[x]==dfn[x]){
        ++num;
        register int j;
        do{
          j=stack[top--];
          in[j]=false;
          belong[j]=num;
        }while(j!=x);
      }
    }
    #define choose(a,b) (((a)<<1)-(b))
    struct Trie{
      Trie *ch[2];
      std::vector<int> mem;
      Trie(){ch[0]=ch[1]=NULL,mem.clear();}
      inline void* operator new(size_t);
    }*root,*C,*mempool;
    inline void* Trie::operator new(size_t){
      if(C==mempool){
        C=new Trie[(1<<15)+10];
        mempool=C+(1<<15)+10;
      }
      return C++;
    }
    inline void build(Trie *p,int id){
      register int i,x,a,b,size=p->mem.size();
      if(!size)return;
      for(i=0;i<size;++i){
        x=p->mem[i];
        if((pos[x]==-1&&pos[id]==-1)||(pos[x]==-1&&pos[id]>=len[x])){
          puts("NO");
          exit(0);
        }
        if(pos[x]==pos[id]){
          add(choose(x,0),choose(id,1));
          add(choose(x,1),choose(id,0));
          add(choose(id,1),choose(x,0));
          add(choose(id,0),choose(x,1));
        }else{
          if(pos[id]==-1||pos[id]>=len[x]){
            if(begin[id][pos[x]]=='1'){
              add(choose(x,1),choose(x,0));
            }else{
              add(choose(x,0),choose(x,1));
            }
          }else{
            if(pos[x]==-1){
              if(begin[x][pos[id]]=='1'){
                add(choose(id,1),choose(id,0));
              }else{
                add(choose(id,0),choose(id,1));
              }
            }else{
              a=begin[id][pos[x]]=='1';
              b=begin[x][pos[id]]=='1';
              add(choose(x,a),choose(id,b^1));
              add(choose(id,b),choose(x,a^1));
            }
          }
        }
      }
    }
    inline void insert(int id){
      register Trie *p=root,*w;
      register int i,j,l=len[id];
      for(i=0;i<l;++i){
        if(begin[id][i]=='?'){
          if(!p->ch[0])
            p->ch[0]=new Trie();
          w=p->ch[0];
          build(w,id);
          for(j=i+1;j<l;++j){
            if(!w->ch[begin[id][j]-'0'])
              w->ch[begin[id][j]-'0']=new Trie();
            w=w->ch[begin[id][j]-'0'];
            build(w,id);
          }
          w->mem.push_back(id);
          if(!p->ch[1])
            p->ch[1]=new Trie();
          w=p->ch[1];
          build(w,id);
          for(j=i+1;j<l;++j){
            if(!w->ch[begin[id][j]-'0'])
              w->ch[begin[id][j]-'0']=new Trie();
            w=w->ch[begin[id][j]-'0'];
            build(w,id);
          }
          w->mem.push_back(id);
          return;
        }
        if(!p->ch[begin[id][i]-'0'])
          p->ch[begin[id][i]-'0']=new Trie();
        p=p->ch[begin[id][i]-'0'];
        build(p,id);
      }
      p->mem.push_back(id);
    }
    inline bool comp(int x,int y){
      return len[x]<len[y];
    }
    inline void Init(){
      root=new Trie();
      scanf("%d",&n);
      register int i,j;
      for(i=1;i<=n;++i){
        pos[i]=-1;
        begin[i]=s+m;
        scanf("%s",s+m);
        len[i]=strlen(s+m);
        m+=len[i];
        temp[i]=i;
        for(j=0;j<len[i];++j)
          if(begin[i][j]=='?'){
            pos[i]=j;
            break;
          }
      }
      std::sort(temp+1,temp+(n+1),comp);
      for(i=1;i<=n;++i){
        insert(temp[i]);
      }
    }
    inline bool check(){
      register int i;
      for(i=1;i<=(n<<1);++i)
        if(!dfn[i])
          Tarjan(i);
      for(i=1;i<=n;++i)
        if(belong[choose(i,1)]==belong[choose(i,0)])
          return false;
      return true;
    }
    int main(){
      //freopen("rio.in","r",stdin);
      Init();
      puts(check()?"YES":"NO");
      return 0;
    }
    88分暴力
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define R register
    const int N=500010;
    struct V{int to,next;}c[N<<6];
    int head[N*10],t;
    inline void add(int x,int y){
      c[++t].to=y,c[t].next=head[x],head[x]=t;
    }
    char s[N];
    int n,cnt;
    int dfn[N*10],low[N*10],belong[N*10],stack[N*10],top,num,Ti;
    bool in[N*10];
    inline void Tarjan(int x){
      dfn[x]=low[x]=++Ti;
      stack[++top]=x;
      in[x]=true;
      R int i;
      for(i=head[x];i;i=c[i].next)
        if(!dfn[c[i].to]){
          Tarjan(c[i].to);
          low[x]=std::min(low[x],low[c[i].to]);
        }else if(in[c[i].to])
          low[x]=std::min(low[x],dfn[c[i].to]);
      if(low[x]==dfn[x]){
        ++num;
        do{
          i=stack[top--];
          in[i]=false;
          belong[i]=num;
        }while(i!=x);
      }
    }
    #define H(a,b) (((a)<<1)-(b))
    struct Trie{
      Trie *ch[2];
      std::vector<int> mem;
      Trie(){ch[0]=ch[1]=NULL,mem.clear();}
      inline void* operator new(size_t);
    }*root,*C,*mempool;
    inline void* Trie::operator new(size_t){
      if(C==mempool){
        C=new Trie[(1<<15)+10];
        mempool=C+(1<<15)+10;
      }
      return C++;
    }
    inline void dfs(Trie *p,int fa){
      if(!p)return;
      R int i,j,x,last=fa,size=p->mem.size();
      for(i=0;i<size;++i){
        x=p->mem[i];
        ++cnt;
        if(x>0)j=1;
        else x=-x,j=0;
        add(H(x,j),H(cnt,1));
        add(H(cnt,0),H(x,j^1));
        add(H(x,j),H(last,0));
        add(H(last,1),H(x,j^1));
        add(H(cnt,0),H(last,0));
        add(H(last,1),H(cnt,1));
        last=cnt;
      }
      ++cnt;
      if(last){
        add(H(cnt,0),H(last,0));
        add(H(last,1),H(cnt,1));
      }
      last=cnt;
      dfs(p->ch[0],last);
      dfs(p->ch[1],last);
    }
    inline void insert(int id){
      scanf("%s",s);
      R Trie *p=root,*w;
      R int i,j,l=strlen(s);
      for(i=0;i<l;++i)s[i]-='0';
      for(i=0;i<l;++i){
        if(s[i]>1){
          w=(!p->ch[0])?p->ch[0]=new Trie():p->ch[0];
          for(j=i+1;j<l;++j)
            w=(!w->ch[s[j]])?w->ch[s[j]]=new Trie():w->ch[s[j]];
          w->mem.push_back(-id);
          w=(!p->ch[1])?p->ch[1]=new Trie():p->ch[1];
          for(j=i+1;j<l;++j)
            w=(!w->ch[s[j]])?w->ch[s[j]]=new Trie():w->ch[s[j]];
          w->mem.push_back(id);
          return;
        }
        p=(!p->ch[s[i]])?p->ch[s[i]]=new Trie():p->ch[s[i]];
      }
      add(H(id,0),H(id,1));
      p->mem.push_back(id);
    }
    inline bool check(){
      R int i;
      for(i=1;i<=(cnt<<1);++i)
        if(!dfn[i])Tarjan(i);
      for(i=1;i<=cnt;++i)
        if(belong[H(i,1)]==belong[H(i,0)])
          return false;
      return true;
    }
    int main(){
      root=new Trie();
      scanf("%d",&n),cnt=n;
      R int i;
      for(i=1;i<=n;++i)insert(i);
      dfs(root,0);
      puts(check()?"YES":"NO");
      return 0;
    }
    100分正解
  • 相关阅读:
    使用jQuery和CSS自定义HTML5 Video 控件 简单适用
    在win7系统下使用Windows XP Mode 和 Windows Virtual PC搭建window xp系统
    Runtime 解读
    Reachability实时监控网络变化
    关于AsyncSocket
    关于CoreData的用法
    邓白氏编码申请
    Android 到底是个什么东西?
    听 Fabien Potencier 谈Symfony2 之 《What is Symfony2 ?》
    听 Fabien Potencier 谈Symfony2 之 《What is Dependency Injection ?》
  • 原文地址:https://www.cnblogs.com/TSHugh/p/8622572.html
Copyright © 2011-2022 走看看