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=;
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的更多相关文章
- Loj 6036 「雅礼集训 2017 Day4」编码 - 2-sat
题目传送门 唯一的传送门 题目大意 给定$n$个串,每个串只包含 ' .问是否可能任意两个不同的串不满足一个是另一个的前缀. 2-sat的是显然的. 枚举每个通配符填0还是1,然后插入Trie树. 对 ...
- loj 6037 「雅礼集训 2017 Day4」猜数列 - 动态规划
题目传送门 传送门 题目大意 有一个位置数列,给定$n$条线索,每条线索从某一个位置开始,一直向左或者向右走,每遇到一个还没有在线索中出现的数就将它加入线索,问最小的可能的数列长度. 依次从左到右考虑 ...
- LOJ #6037.「雅礼集训 2017 Day4」猜数列 状压dp
这个题的搜索可以打到48分…… #include <cstdio> #include <cstring> #include <algorithm> ; bool m ...
- 2018.10.27 loj#6035. 「雅礼集训 2017 Day4」洗衣服(贪心+堆)
传送门 显然的贪心题啊...考试没调出来10pts滚了妙的一啊 直接分别用堆贪心出洗完第iii件衣服需要的最少时间和晾完第iii件衣服需要的最少时间. 我们设第一个算出来的数组是aaa,第二个是bbb ...
- LOJ#6035. 「雅礼集训 2017 Day4」洗衣服
传送门 先处理出每一件衣服最早什么时候洗完,堆+贪心即可 然后同样处理出每件衣服最早什么时候烘干 然后倒序相加取最大值 # include <bits/stdc++.h> using na ...
- LOJ #6035.「雅礼集训 2017 Day4」洗衣服 贪心
这道题的贪心好迷啊~我们对于两个过程进行单独贪心,然后再翻转一个,把这两个拼起来.先说一下单独贪心,单独贪心的话就是用一个堆,每次取出最小的,并且把这个最小的加上他单次的,再放进去.这样,我们得到的结 ...
- 【LOJ6036】 「雅礼集训 2017 Day4」编码
传送门 LOJ Solution 因为?只有两种可能为0,1,所以就把这两个串搞出来. 那么现在?取0和?取1不能并存,前缀不能并存,所以就是一个\(2-SAT\),现在问题在于这个东西可能会有很多条 ...
- [LOJ 6031]「雅礼集训 2017 Day1」字符串
[LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...
- [LOJ 6030]「雅礼集训 2017 Day1」矩阵
[LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...
随机推荐
- java.lang.Boolean.valueOf(String s)
简单说,就是s为true(这四个字母大小写任意)时,返回值为true,否则为false public class one { public static void main(String[] args ...
- HDU-1053:Advanced Fruits(LCS+路径保存)
链接:HDU-1053:Advanced Fruits 题意:将两个字符串合成一个串,不改变原串的相对顺序,可将相同字母合成一个,求合成后最短的字符串. 题解:LCS有三种状态转移方式,将每个点的状态 ...
- Elasticsearch.Net 异常:[match] query doesn't support multiple fields, found [field] and [query]
用Elasticsearch.Net检索数据,报异常: )); ElasticLowLevelClient client = new ElasticLowLevelClient(settings); ...
- Python爬虫入门(6):Cookie的使用
为什么要使用Cookie呢? Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密) 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓 ...
- 关于0x80000000为什么等于-2147483648和负数在内存上储存的问题
转载自大佬的博客https://blog.csdn.net/youyou362/article/details/72667951/ 1·先说明负数怎么储存 (1)十进制负数是以其补码储存在内存上. 验 ...
- c# byte转docx
问题情境: docx文件放进resource中,再用程序读出来的时候是二进制数组. 解决办法: public string ByteConvertWord(byte[] data, string fi ...
- Floyd算法(原理|代码实现)
http://www.cnblogs.com/twjcnblog/archive/2011/09/07/2170306.html 正如我们所知道的,Floyd算法用于求最短路径.Floyd算法可以说是 ...
- java程序连接MySQL数据库
驱动程序:mysql-connector-java-5.1.7-bin.jar. 程序示例如下: package commonProject; import java.sql.Connection; ...
- RequestMappingHandlerMapping 详解
我们先理简单梳理一个关系 关系梳理 spring ioc 是spring的核心,用来管理spring bean的生命周期 MVC 是一种使用 MVC(Model View Controller 模型- ...
- 软工网络15团队作业4——Alpha阶段敏捷冲刺-6
一.当天站立式会议照片: 二.项目进展 昨天已完成的工作: 完成对账单的编辑,删除等操作,以及开始服务器的编写工作 明天计划完成的工作: 记账功能基本完成,进一步优化功能与完善服务器 工作中遇到的困难 ...