P6965 [NEERC2016]Binary Code
注意到每个串只有一个 ? (只有
于是进一步想到如果
那么容易想到暴力
考虑使用 trie,那么对于一个状态
可以复制一遍 trie,trie 树上儿子连父亲,然后
inline void build1(){
for(register int i=1; i<=trie_cnt; i++) if(fa(i)) Add_Edge(i+node_cnt,fa(i)+node_cnt);
for(register int i=1, x; i<=n; i++){
x = loc[0][i]; if(x) Add_Edge(x+node_cnt,Y(i)); if(fa(x)) Add_Edge(N(i),fa(x)+node_cnt);
x = loc[1][i]; if(x) Add_Edge(x+node_cnt,N(i)); if(fa(x)) Add_Edge(Y(i),fa(x)+node_cnt);
}
node_cnt += trie_cnt;
}
还是复制一遍 trie,父亲连儿子,然后
inline void build2(){
for(register int i=1; i<=trie_cnt; i++) if(fa(i)) Add_Edge(fa(i)+node_cnt,i+node_cnt);
for(register int i=1, x; i<=n; i++){
x = loc[0][i]; if(x) Add_Edge(N(i),x+node_cnt); if(fa(x)) Add_Edge(fa(x)+node_cnt,Y(i));
x = loc[1][i]; if(x) Add_Edge(Y(i),x+node_cnt); if(fa(x)) Add_Edge(fa(x)+node_cnt,N(i));
}
node_cnt += trie_cnt;
}
设点
inline void build3(){
static int tmp[MAXN], num;
for(register int i=1; i<=trie_cnt; i++){
num = vec[i].size();
if(num>=2){
for(register int j=1; j<=num; j++)
tmp[j] = vec[i][j-1],
Add_Edge(tmp[j],j+node_cnt),
Add_Edge(j+num+node_cnt,tmp[j]^1);
for(register int j=1; j<num; j++)
Add_Edge(j+node_cnt,j+1+node_cnt),
Add_Edge(j+node_cnt,tmp[j+1]^1),
Add_Edge(tmp[j+1],j+num+node_cnt),
Add_Edge(j+1+num+node_cnt,j+num+node_cnt);
node_cnt += num*2;
}
}
}
然后走一般 2-SAT 流程就行了,输出方案看哪个状态的
一点小细节
仔细看题,最多一个"?",意思是会有没有 ? 的字符串(样例2),这种情况可以假设任意一位为 ? ,然后强制这一位选
完整代码