第一眼觉得和一道题莫名相似,实际上并没有什么关系
ft,i,j
表示从第
i
个点,第
一开始假设掉在房间中间,那我们按照顺序把所有点走过去一遍,取个最小表示,Hash在一起
最后Hash值相同的就是等价了
应该是有不Hash的确定算法的?谁知道呢
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<algorithm>
#define pb push_back
using namespace std;
typedef unsigned long long ull;
#define read(x) scanf("%d",&(x))
const int N=105;
int n;
int G[N][N],back[N][N];
ull H[N][N][N];
const ull ORI1=2333,ORI2=23333;
const ull BASE1=999911657,BASE2=999911659;
const ull END1=18357,END2=81643;
ull HH[N];
bool cmp(int x,int y){
return HH[x]==HH[y]?x<y:HH[x]<HH[y];
}
ull lst[N],pnt;
int idx[N];
inline int mpa(ull *a,int n){
int i = 0, j = 1, k = 0;
while(i < n && j < n && k < n){
ull x=a[(i + k) % n],y=a[(j + k) % n];
if(x==y) k ++;
else{
if(x>y) i += k + 1;
else j += k + 1;
if(i == j) i ++;
}
}
return min(i, j);
}
int cnt;
int K[N][N];
inline bool cmp2(int x,int y){
return K[x][1]<K[y][1];
}
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
for (int i=1;i<=n;i++){
read(*G[i]); for (int j=1;j<=*G[i];j++) read(G[i][j]),back[i][G[i][j]]=j;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=*G[i];j++)
H[0][i][j]=(ull)(*G[i]);
for (int t=1;t<=n;t++)
for (int i=1;i<=n;i++)
for (int j=1;j<=*G[i];j++){
H[t][i][j]=ORI1;
for (int k=j,c=1;c<=*G[i];k=k%*G[i]+1,c++){
int v=G[i][k]; ull h=H[t-1][v][back[v][i]];
(((H[t][i][j]*=BASE1)+=h)^=h)+=h;
}
((H[t][i][j]+=END1)*=END1)^=END1;
}
for (int i=1;i<=n;i++){
pnt=0;
for (int j=1;j<=*G[i];j++){
ull hh=ORI2,h; int v=G[i][j];
for (int t=0;t<=n;t++)
h=H[t][v][back[v][i]],(((hh*=BASE2)+=h)^=h)+=h;
((hh+=END2)*=END2)^=END2;
lst[++pnt]=hh;
}
int x=mpa(lst+1,pnt)+1;
HH[i]=ORI2;
for (int j=x,c=1;c<=pnt;j=j%pnt+1,c++)
(((HH[i]*=BASE2)+=lst[j])^=lst[j])+=lst[j];
((HH[i]+=END2)*=END2)^=END2;
}
for (int i=1;i<=n;i++) idx[i]=i;
sort(idx+1,idx+n+1,cmp); int flag=0;
for (int i=1,j;i<=n;i=j+1){
j=i; while (j+1<=n && HH[idx[i]]==HH[idx[j+1]]) j++;
if (j-i+1>1){
flag=1; ++cnt;
for (int k=i;k<=j;k++)
K[cnt][++*K[cnt]]=idx[k];
}
}
if (!flag)
printf("none\n");
else{
for (int i=1;i<=cnt;i++) idx[i]=i;
sort(idx+1,idx+cnt+1,cmp2);
for (int i=1;i<=cnt;i++){
int x=idx[i];
for (int j=1;j<=*K[x];j++)
printf("%d%c",K[x][j],j==*K[x]?'\n':' ');
}
}
return 0;
}