LOJ6036编码

每个串拆成两个,都插入trie数。
把trie树建出来后,每一条从根到叶子的链上最多只能有一个变量为1。
这是个经典的前后缀优化2-sat建图的套路。
树上的做法也就是边dfs边做而已。

#include<bits/stdc++.h>
#define N 3300000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
using namespace std;
inline int read()
{
	char ch=0;
	int x=0,flag=1;
	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*flag;
}
struct edge{int to,nxt;}e[N*4];
int num,head[N];
inline void add(int x,int y){e[++num]=(edge){y,head[x]};head[x]=num;}
stack<int>st;
bool in_stack[N];
int times,bel_cnt,dfn[N],low[N],bel[N];
void tarjan(int x)
{
	dfn[x]=low[x]=++times;
	st.push(x);in_stack[x]=true;
	for(int i=head[x];i!=-1;i=e[i].nxt)
	{
		int to=e[i].to;
		if(!dfn[to])tarjan(to),low[x]=min(low[x],low[to]);
		else if(in_stack[to])low[x]=min(low[x],dfn[to]);
	}
	if(dfn[x]==low[x])
	{
		bel_cnt++;
		int u;
		do
		{
			u=st.top();st.pop();
			bel[u]=bel_cnt;
			in_stack[u]=false;
		}while(x!=u);
	}
}
char s[N];
int size,f[N],p[N],pre[N];
struct Trie
{
	#define lson son[x][0]
	#define rson son[x][1]
	#define mid ((l+r)>>1)
	vector<int>v[N];
	int root=1,cnt=0,tot=1,son[N][2];
	void insert(int n,int id)
	{
		int x=root;
		for(int i=1;i<=n;i++)
		{
			int k=s[i]-'0';
			if(!son[x][k])son[x][k]=++tot;
			x=son[x][k];
		}
		v[x].push_back(id);
	}
	void dfs(int x)
	{
		int len=v[x].size();
		for(int i=0;i<len;i++)
		{
			p[++cnt]=v[x][i];
			pre[p[cnt]]=++size;
			f[pre[p[cnt]]]=++size;
			f[size]=pre[p[cnt]];
			add(p[cnt],pre[p[cnt]]);
			add(f[pre[p[cnt]]],f[p[cnt]]);
			if(cnt!=1)
			{
				add(pre[p[cnt-1]],pre[p[cnt]]);
				add(f[pre[p[cnt]]],f[pre[p[cnt-1]]]);
				add(pre[p[cnt-1]],f[p[cnt]]);
				add(p[cnt],f[pre[p[cnt-1]]]);
			}
		}
		if(lson)dfs(lson);if(rson)dfs(rson);cnt-=len;
	}
}T;
int main()
{
	int n=read();size=n;
	num=-1;memset(head,-1,sizeof(head));
	for(int o=1;o<=n;o++)
	{
		scanf("%s",s+1);
		int k=0,len=strlen(s+1);
		for(int i=1;i<=len;i++)if(s[i]=='?')k=i;
		f[o]=++size;f[size]=o;
		if(k)
		{
			s[k]='0';T.insert(len,f[o]);
			s[k]='1';T.insert(len,o);
		}
		else add(f[o],o),T.insert(len,o);
	}
	T.dfs(T.root);
	for(int i=1;i<=size;i++)if(!dfn[i])tarjan(i);
	for(int i=1;i<=size;i++)if(bel[i]==bel[f[i]]){printf("NO");return 0;}
	printf("YES");
	return 0;
}
posted @ 2019-02-28 09:56  Creed-qwq  阅读(275)  评论(0编辑  收藏  举报