呜呜~我想半天都不会……解决这个问题,后来看了题解

瓶颈在于这个对立点跟其余跟它字符串相等的点(所谓当前挂在同一个trie节点上的点),如果不暴力连的话总是互相牵连
所以就强制同一个trie节点上的点的父子关系,每个点拆出来,具体可见code的Add_trie。
然后对立点就独立了。

又有问题了?怎么把它独立出来,连它父亲,它儿子好像怎么会多余两个点。

然后就想到把trie'树拆成两棵,出树和入树
总结一下:
本来每个点连向对应trie'的点,每个trie'的点连向该对立点。满足我们的目的(无论子树内还是祖先上下都能由原节点传到对立点)
为了排除u->u':出树中原节点连对应点的父亲,入树中对立点由原树中该点的父亲连入

  • code
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=3e6+5;
const int M=2;
int fa[N],_[N],to[N<<1],head[N],nxt[N<<1],go[N][M],ecnt,ncnt,num;
int n,nn,mark[N],pos[N];
char s[N];
vector<int>V[N];
void add_edge(int u,int v) {nxt[++ecnt]=head[u];to[ecnt]=v;head[u]=ecnt;}
void Insert(int id) {
	int u=0,len=strlen(s);
	for(int i=0;i<len;i++) {
		int d=s[i]-'0';
		if(!go[u][d])go[u][d]=++ncnt;
		u=go[u][d];
	}
	V[u].push_back(id);
}
void Add_trie(int u,int fr) {
	for(int d=0;d<=1;d++) {
		int x=go[u][d],sz,tmp=fr;
		if(!x)continue;
		for(int j=0;j<V[x].size();j++) {
			int y=V[x][j];pos[y]=++num;
			fa[pos[y]]=fr;
			add_edge(pos[y],fr);add_edge(fr+nn,pos[y]+nn);fr=pos[y];
		}
		Add_trie(x,fr);fr=tmp;
	}
}
void init2() {
	for(int i=1;i<=(n<<1);i++) {
		int f=fa[pos[i]];
		add_edge(i,f),add_edge(pos[i],_[i]),add_edge(i,pos[i]+nn),add_edge(f+nn,_[i]);
	}
}
int dfn[N],low[N],Time,st[N],tp,Bl[N],SCC;
bool In_s[N];
void Tarjan(int u) {
	In_s[st[++tp]=u]=1;dfn[u]=low[u]=++Time;
	for(int i=head[u];i;i=nxt[i]) {
		int v=to[i];
		if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]);
		else if(In_s[v])low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u]) {
		++SCC;int v;
		do {
			v=st[tp--];In_s[v]=0;Bl[v]=SCC;
		}while(u!=v);
	}
}
bool _rd() {for(int i=1;i<=n;i++)if(Bl[i]==Bl[_[i]])return 0;return 1;}
int main() {
//	freopen("data.in","r",stdin);
	scanf("%d",&n);num=ncnt=nn=n<<1;num++;nn++;
	for(int i=1;i<=n;i++) {
		_[i]=i+n,_[i+n]=i;
		scanf("%s",s);int len=strlen(s);
		bool flag=0;
		for(int j=0;j<len;j++)if(s[j]=='?') {
			s[j]='0',Insert(i);s[j]='1',Insert(_[i]);flag=1;break;
		}
		if(flag)continue;
		Insert(i);s[0]=s[0]=='0'?'1':'0';Insert(_[i]);add_edge(_[i],i);
	}
	Add_trie(0,num);
	init2();
	for(int i=1;i<=num+nn;i++)if(!dfn[i])Tarjan(i);
	if(_rd()) printf("YES");
	else printf("NO");
	return 0;
}