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. 无解 ...
 
随机推荐
- unittest,requests——接口测试脚本及报告
			
用unittest管理两个利用requests模块,做百度搜索的简单接口测试用例,之后自动输出报告 # encoding=utf-8import requests,unittest,HTMLTestR ...
 - Java跨平台的实现原理
			
不同操作系统支持的指令集有所差异,只要在不同操作系统上安装对应的jvm,jvm负责把Java字节码翻译成对应机器的二进制码,从而实现java语言的跨平台.
 - HttpServlet 详解(基础)
			
HttpServlet详解 大家都知道Servlet,但是不一定很清楚servlet框架,这个框架是由两个Java包组成:javax.servlet和javax.servlet.http. 在java ...
 - 《Linux内核与分析》第七周
			
by 21035130王川东 Linux内核如何装载和启动一个可执行程序 一. EIF文件格式: 1.ELF头部在文件的开始,描述文件的总体格式,保存了路线图,描述该文件的组织情况,即生成该文件系统的 ...
 - Codeforces Beta Round #14 (Div. 2) D. Two Paths 树的直径
			
题目链接: http://codeforces.com/contest/14/problem/D D. Two Paths time limit per test2 secondsmemory lim ...
 - C语言的调查
			
1.你对自己的未来有什么规划?做了哪些准备?从事跟本专业相关的工作.认真学习好书本的知识,并能很好的运用它. 2.你认为什么是学习?学习有什么用?现在学习动力如何?为什么?学习可以让自己懂得更多,完善 ...
 - BETA阶段第一天
			
1.提供当天站立式会议照片一张 2.每个人的工作 今天完成工作 林一心 服务器调试 张杭镖 数据库调整 赵意 前端设计 江鹭涛 前端设计 3.发布项目燃尽图 4.每日每人总结 林一心:服务器端的配置不 ...
 - tftp 简要使用说明
			
yum 安装:tftp tftp-server (2)启动tftp CentOS 6 service xinetd restart chkconfig tftp on CentOS ...
 - oracle & 的用法!
			
/*select * from emp_bak where deptno = &"Department number" order by ename; select * f ...
 - 控件属性和InitializeComponent()关系:
			
namespace Test22 { partial class Form1 { /// <summary> /// 必需的设计器变量. /// </summary> priv ...