JZOJ5010. 编码
来源:互联网 发布:oracle 自动优化 工具 编辑:程序博客网 时间:2024/05/29 20:00
题目大意
给定
Data Constraint
题解
考虑用Trie建图,跑2-SAT
将所有可能的串加入一个Trie里,每个点向它根路径上经过的点的另一个连边,表示这两种不能同时选。
然后Tarjan判一下就好了。
时间复杂度:
SRC
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std ;#define N 5000000 + 10#define M 500000 + 10struct Trie { int Son[2] , fa ; int In , Out , use ;} T[2*M] ;vector < int > P[2*M] ;char S[N] ;bool ok = 1 ;bool vis[N] , flag[N] ;int Node[5*N] , Next[5*N] , Head[N] , tot ;int DFN[N] , LOW[N] , Sta[N] , Bel[N] , Time ;int from[N] , Pre[N] , Suf[N] ;int n , Cnt , Col , Amo , Num = 1 ;void link( int u , int v ) { Node[++tot] = v ; Next[tot] = Head[u] ; Head[u] = tot ;}int Rev( int x ) { if ( x > 2 * n ) return 0 ; return x > n ? x - n : x + n ;}void Insert( int len , int ID ) { int now = 1 ; for (int i = 1 ; i <= len ; i ++ ) { int c = S[i] - '0' ; if ( !T[now].Son[c] ) { T[now].Son[c] = ++ Num ; T[Num].fa = now ; } now = T[now].Son[c] ; } if ( !T[now].use ) T[now].use = ++ Amo ; P[T[now].use].push_back( ID ) ; if ( !T[now].In ) T[now].In = ++ Cnt ; if ( !T[now].Out ) T[now].Out = ++ Cnt ; link( T[now].In , Rev(ID) ) ; link( ID , T[now].Out ) ; from[ID] = now ;}void Build( int st ) { if ( vis[st] ) return ; vis[st] = 1 ; int siz = P[T[st].use].size() ; Pre[0] = Suf[siz+1] = 0 ; for (int i = 1 ; i <= siz ; i ++ ) { int now = Rev(P[T[st].use][i-1]) ; Pre[i] = ++ Cnt ; if ( Pre[i-1] > 0 ) link( Pre[i] , Pre[i-1] ) ; link( Pre[i] , now ) ; } for (int i = siz ; i >= 1 ; i -- ) { int now = Rev(P[T[st].use][i-1]) ; Suf[i] = ++ Cnt ; if ( Suf[i+1] > 0 ) link( Suf[i] , Suf[i+1] ) ; link( Suf[i] , now ) ; } for (int i = 1 ; i <= siz ; i ++ ) { int now = P[T[st].use][i-1] ; if ( Pre[i-1] > 0 ) link( now , Pre[i-1] ) ; if ( Suf[i+1] ) link( now , Suf[i+1] ) ; } int last = st ; for (int x = T[st].fa ; x != 1 ; x = T[x].fa ) { if ( T[x].In == 0 ) continue ; link( T[last].Out , T[x].In ) ; link( T[x].Out , T[last].In ) ; }}void Tarjan( int x ) { Sta[++Sta[0]] = x ; flag[x] = 1 ; DFN[x] = LOW[x] = ++ Time ; for (int p = Head[x] ; p ; p = Next[p] ) { if ( !DFN[Node[p]] ) { Tarjan( Node[p] ) ; LOW[x] = min( LOW[x] , LOW[Node[p]] ) ; } else if ( flag[Node[p]] ) LOW[x] = min( LOW[x] , DFN[Node[p]] ) ; if ( !ok ) return ; } if ( DFN[x] == LOW[x] ) { Col ++ ; while ( Sta[0] ) { int now = Sta[Sta[0]] ; Bel[now] = Col ; flag[now] = 0 ; Sta[0] -- ; if ( Bel[now] == Bel[Rev(now)] ) { ok = 0 ; return ; } if ( now == x ) break ; } }}bool Check() { for (int i = 1 ; i <= 2 * n ; i ++ ) { if ( !DFN[i] ) Tarjan( i ) ; if ( !ok ) return 0 ; } return 1 ;}int main() { freopen( "code.in" , "r" , stdin ) ; freopen( "code.out" , "w" , stdout ) ; scanf( "%d" , &n ) ; Cnt = 2 * n ; for (int i = 1 ; i <= n ; i ++ ) { scanf( "%s" , S + 1 ) ; int len = strlen( S + 1 ) , wz = 0 ; for (int j = 1 ; j <= len ; j ++ ) { if ( S[j] == '?' ) wz = j ; } if ( !wz ) Insert( len , i ) , link( n + i , i ) ; else { from[i] = from[n+i] = 1 ; S[wz] = '0' ; Insert( len , i ) ; S[wz] = '1' ; Insert( len , n + i ) ; } } for (int i = 1 ; i <= 2 * n ; i ++ ) { if ( !from[i] ) continue ; Build( from[i] ) ; } if ( Check() ) printf( "YES\n" ) ; else printf( "NO\n" ) ; return 0 ;}
以上.
1 0
- JZOJ5010. 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 编码
- 第0节 C语言入门之终端命令
- 对web网站模拟压力测试
- 多条件查询数据列表并进行分页
- Android 开启之旅-学习路线
- hibernate中的一对多双向关联
- JZOJ5010. 编码
- 华为2017年实习面试面经(研发类)
- JS的内建函数reduce
- NSURLSessionDataTask
- Caffe学习系列(7):solver及其配置
- Hbase伪分布式
- docker 网络 不好用 docker: Error response from daemon: failed to create endpoint jovial_wing on network b
- 浅析邮件服务
- 编程珠玑 笔记