BZOJ3421 : Poi2013 Walk
最多只有一个连通块大小大于$nk$,所以用hash表进行BFS的时候只扩展$nk$步即可。
时间复杂度$O(n^2k)$。
#include<cstdio> typedef long long ll; const int N=5001000,M=9999991; int n,m,lim,i,h=1,t,g[M],nxt[N],ed;ll v[N],a[N/5],q[N],x,S,T;char s[70]; inline void del(ll x){ int u=x%M; v[ed]=x;nxt[ed]=g[u];g[u]=ed++; } inline void add(ll x){ int u=x%M; for(int i=g[u];i;i=nxt[i])if(v[i]==x)return; v[ed]=x;nxt[ed]=g[u];g[u]=ed++;q[++t]=x; } inline ll read(){ ll t=0; scanf("%s",s); for(int i=0;i<n;i++)t=t*2+s[i]-'0'; return t; } int main(){ scanf("%d%d",&n,&m);lim=n*m+5; add(S=read());T=read(); for(i=0;i<m;i++)del(a[i]=read()); while(h<=t&&t<=lim){ x=q[h++]; if(x==T)return puts("TAK"),0; for(i=0;i<n;i++)add(x^(1LL<<i)); } if(t<=lim)return puts("NIE"),0; for(h=1,t=ed=i=0;i<M;i++)g[i]=0; add(T); for(i=0;i<m;i++)del(a[i]); while(h<=t&&t<=lim){ x=q[h++]; if(x==S)return puts("TAK"),0; for(i=0;i<n;i++)add(x^(1LL<<i)); } return puts(t<=lim?"NIE":"TAK"),0; }