洛谷的翻译不太清楚,这里是acwing题目链接:https://www.acwing.com/problem/content/139/
题解
算法:hash
+邻接表+(最小表示法)
过程:
-
读入雪花 a a a,进行
hash
,得到一个值 h h h -
如果邻接表中有
hash
值为 h h h 的雪花,依次遍历这些雪花,与雪花 a a a 进行比较是否相同(可以使用暴力或最小表示法) -
如果相同输出
Twin snowflakes found.
,否则继续读入
代码:
//SP4354
#include <cstring>
#include <cstdio>
typedef long long ll;
const int N=100010,P=99991;
int n,Snow[N][6],Head[N],Next[N],tot,a[10];
int Hash(int *a){
// Hash 函数
// Hash(a) = sum(i=1->6){a[i]}+mul(i=1->6){a[i]}
int sum=0,mul=1;
for(int i=0; i<6; ++i)
sum=(sum+a[i])%P, mul=(ll)mul*a[i]%P;
return (sum+mul)%P;
}
bool isequal(int *a,int *b){
//判断两片雪花是否相等
//暴力枚举两片雪花的“起始角”
//判断一下,第二片翻过来再判断一下
for(int i=0; i<6; ++i){
for(int j=0; j<6; ++j){
bool yes=true;
for(int k=0; k<6; ++k) if(a[(i+k)%6]!=b[(j+k)%6]) yes=false;
if(yes) return true;
yes=true;
for(int k=0; k<6; ++k) if(a[(i+k)%6]!=b[(j-k+6)%6]) yes=false;
if(yes) return true;
}
}
return false;
}
bool findandinsert(int *a){
//链式前向星邻接表
int h=Hash(a);
for(int i=Head[h]; i; i=Next[i])
if(isequal(Snow[i],a)) return true;
++tot;
memcpy(Snow[tot],a,6*sizeof(int));
Next[tot]=Head[h],Head[h]=tot;
return false;
}
int main(){
scanf("%d",&n);
for(int i=1; i<=n; ++i){
for(int j=0; j<6; ++j)
scanf("%d",&a[j]);
if(findandinsert(a))
return puts("Twin snowflakes found.")&0;
}
return puts("No two snowflakes are alike.")&0;
}
//qwq~~