记得之前做过几道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=;
struct V{
int to,next;
}c[N<<];
int head[N<<],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<<],low[N<<],belong[N<<],stack[N<<],top,num,Ti;
bool in[N<<];
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[];
std::vector<int> mem;
Trie(){ch[]=ch[]=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[(<<)+];
mempool=C+(<<)+;
}
return C++;
}
inline void build(Trie *p,int id){
register int i,x,a,b,size=p->mem.size();
if(!size)return;
for(i=;i<size;++i){
x=p->mem[i];
if((pos[x]==-&&pos[id]==-)||(pos[x]==-&&pos[id]>=len[x])){
puts("NO");
exit();
}
if(pos[x]==pos[id]){
add(choose(x,),choose(id,));
add(choose(x,),choose(id,));
add(choose(id,),choose(x,));
add(choose(id,),choose(x,));
}else{
if(pos[id]==-||pos[id]>=len[x]){
if(begin[id][pos[x]]==''){
add(choose(x,),choose(x,));
}else{
add(choose(x,),choose(x,));
}
}else{
if(pos[x]==-){
if(begin[x][pos[id]]==''){
add(choose(id,),choose(id,));
}else{
add(choose(id,),choose(id,));
}
}else{
a=begin[id][pos[x]]=='';
b=begin[x][pos[id]]=='';
add(choose(x,a),choose(id,b^));
add(choose(id,b),choose(x,a^));
}
}
}
}
}
inline void insert(int id){
register Trie *p=root,*w;
register int i,j,l=len[id];
for(i=;i<l;++i){
if(begin[id][i]=='?'){
if(!p->ch[])
p->ch[]=new Trie();
w=p->ch[];
build(w,id);
for(j=i+;j<l;++j){
if(!w->ch[begin[id][j]-''])
w->ch[begin[id][j]-'']=new Trie();
w=w->ch[begin[id][j]-''];
build(w,id);
}
w->mem.push_back(id);
if(!p->ch[])
p->ch[]=new Trie();
w=p->ch[];
build(w,id);
for(j=i+;j<l;++j){
if(!w->ch[begin[id][j]-''])
w->ch[begin[id][j]-'']=new Trie();
w=w->ch[begin[id][j]-''];
build(w,id);
}
w->mem.push_back(id);
return;
}
if(!p->ch[begin[id][i]-''])
p->ch[begin[id][i]-'']=new Trie();
p=p->ch[begin[id][i]-''];
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=;i<=n;++i){
pos[i]=-;
begin[i]=s+m;
scanf("%s",s+m);
len[i]=strlen(s+m);
m+=len[i];
temp[i]=i;
for(j=;j<len[i];++j)
if(begin[i][j]=='?'){
pos[i]=j;
break;
}
}
std::sort(temp+,temp+(n+),comp);
for(i=;i<=n;++i){
insert(temp[i]);
}
}
inline bool check(){
register int i;
for(i=;i<=(n<<);++i)
if(!dfn[i])
Tarjan(i);
for(i=;i<=n;++i)
if(belong[choose(i,)]==belong[choose(i,)])
return false;
return true;
}
int main(){
//freopen("rio.in","r",stdin);
Init();
puts(check()?"YES":"NO");
return ;
}

88分暴力

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define R register
const int N=;
struct V{int to,next;}c[N<<];
int head[N*],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*],low[N*],belong[N*],stack[N*],top,num,Ti;
bool in[N*];
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[];
std::vector<int> mem;
Trie(){ch[]=ch[]=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[(<<)+];
mempool=C+(<<)+;
}
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=;i<size;++i){
x=p->mem[i];
++cnt;
if(x>)j=;
else x=-x,j=;
add(H(x,j),H(cnt,));
add(H(cnt,),H(x,j^));
add(H(x,j),H(last,));
add(H(last,),H(x,j^));
add(H(cnt,),H(last,));
add(H(last,),H(cnt,));
last=cnt;
}
++cnt;
if(last){
add(H(cnt,),H(last,));
add(H(last,),H(cnt,));
}
last=cnt;
dfs(p->ch[],last);
dfs(p->ch[],last);
}
inline void insert(int id){
scanf("%s",s);
R Trie *p=root,*w;
R int i,j,l=strlen(s);
for(i=;i<l;++i)s[i]-='';
for(i=;i<l;++i){
if(s[i]>){
w=(!p->ch[])?p->ch[]=new Trie():p->ch[];
for(j=i+;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[])?p->ch[]=new Trie():p->ch[];
for(j=i+;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,),H(id,));
p->mem.push_back(id);
}
inline bool check(){
R int i;
for(i=;i<=(cnt<<);++i)
if(!dfn[i])Tarjan(i);
for(i=;i<=cnt;++i)
if(belong[H(i,)]==belong[H(i,)])
return false;
return true;
}
int main(){
root=new Trie();
scanf("%d",&n),cnt=n;
R int i;
for(i=;i<=n;++i)insert(i);
dfs(root,);
puts(check()?"YES":"NO");
return ;
}

100分正解

LOJ #6036.「雅礼集训 2017 Day4」编码 Trie树上2-sat的更多相关文章

  1. Loj 6036 「雅礼集训 2017 Day4」编码 - 2-sat

    题目传送门 唯一的传送门 题目大意 给定$n$个串,每个串只包含 ' .问是否可能任意两个不同的串不满足一个是另一个的前缀. 2-sat的是显然的. 枚举每个通配符填0还是1,然后插入Trie树. 对 ...

  2. loj 6037 「雅礼集训 2017 Day4」猜数列 - 动态规划

    题目传送门 传送门 题目大意 有一个位置数列,给定$n$条线索,每条线索从某一个位置开始,一直向左或者向右走,每遇到一个还没有在线索中出现的数就将它加入线索,问最小的可能的数列长度. 依次从左到右考虑 ...

  3. LOJ #6037.「雅礼集训 2017 Day4」猜数列 状压dp

    这个题的搜索可以打到48分…… #include <cstdio> #include <cstring> #include <algorithm> ; bool m ...

  4. 2018.10.27 loj#6035. 「雅礼集训 2017 Day4」洗衣服(贪心+堆)

    传送门 显然的贪心题啊...考试没调出来10pts滚了妙的一啊 直接分别用堆贪心出洗完第iii件衣服需要的最少时间和晾完第iii件衣服需要的最少时间. 我们设第一个算出来的数组是aaa,第二个是bbb ...

  5. LOJ#6035. 「雅礼集训 2017 Day4」洗衣服

    传送门 先处理出每一件衣服最早什么时候洗完,堆+贪心即可 然后同样处理出每件衣服最早什么时候烘干 然后倒序相加取最大值 # include <bits/stdc++.h> using na ...

  6. LOJ #6035.「雅礼集训 2017 Day4」洗衣服 贪心

    这道题的贪心好迷啊~我们对于两个过程进行单独贪心,然后再翻转一个,把这两个拼起来.先说一下单独贪心,单独贪心的话就是用一个堆,每次取出最小的,并且把这个最小的加上他单次的,再放进去.这样,我们得到的结 ...

  7. 【LOJ6036】 「雅礼集训 2017 Day4」编码

    传送门 LOJ Solution 因为?只有两种可能为0,1,所以就把这两个串搞出来. 那么现在?取0和?取1不能并存,前缀不能并存,所以就是一个\(2-SAT\),现在问题在于这个东西可能会有很多条 ...

  8. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

  9. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

随机推荐

  1. Centos下安装并设置nginx开机自启动

    一.在centos环境下安装下载并安装nginx,由于nginx需要依赖一些环境才能安装,主要依赖g++.gcc.openssl-devel.pcre-devel和zlib-devel这些环境,首先得 ...

  2. 422. Length of Last Word【LintCode java】

    Description Given a string s consists of upper/lower-case alphabets and empty space characters ' ', ...

  3. [T-ARA/筷子兄弟][Little Apple]

    歌词来源:http://music.163.com/#/song?id=29753511 作曲 : 筷子兄弟 [作曲 : 筷子兄弟] 作词 : K-Smith [作词 : KSmith] 编曲 : 新 ...

  4. 17 Tips For Writing An Excellent Email Subject Line

    Out of the billions of emails that are sent every day, how can you make sure that yours stands out? ...

  5. Python爬虫入门(7):正则表达式

    下面就开始介绍一个十分强大的工具,正则表达式! 1.了解正则表达式 正则表达式是对字符串操作的一种公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串” ...

  6. ES6中Class的继承关系

    es5实现中,每个对象都有__proto__属性(也就是关系图中[[prototype]]属性),指向对应的构造函数的prototype.Class 作为构造函数的语法糖,同时有prototype属性 ...

  7. CS小分队第二阶段冲刺站立会议(5月28日)

    昨日成果:昨天对我们的软件的主界面进行了思考,考虑到许多人建议我们团队添加可以自主增加软件快捷键的功能,我对这一想法的可行性和项目总体策划进行评估分析后,决定正式实施:已经完成从电脑上添加文件在我们的 ...

  8. CS小分队第一阶段冲刺站立会议(5月11日)

    昨日成果:完成了倒计时器的制作,为其添加了声音:并对扫雷游戏的失败添加了动态效果: 遇到的困难:把图片放入picturebox中无法改变图片的大小,音乐格式只能使用.wav,该格式音乐比较大,增加了整 ...

  9. static块的本质

    在网上看到了下面的一段代码: public class Test { static { _i = 20; } public static int _i = 10; public static void ...

  10. 第十一次作业 - Alpha 事后诸葛亮(团队)

    软工 · 第十一次作业 - Alpha 事后诸葛亮(团队) 组长本次作业链接 现代软件工程 项目Postmortem 设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场 ...