Baekjoon-8049 The Labyrinth of Wells 题解
前言
这个题好冷门,不知道某某 OI 知名教练怎么找出来的。
正文
0x00 题目分析
题面有点绕(没某某 OI 知名教练,出的模拟赛改版题面绕)。但是分析一下就是,抽象为:一个 DAG 每个点有一个点权,每条边有一个边权,对于图上任意一条路径的边权和点权按照访问顺序链接成两个有序序列,这两个序列设其为这个路径的代表元,然后对于所有的路径生成的代表原形成一个集合
分析一下由于最终要到
那么用 hash (乱记一通)记录每个点为起点生成的代表集合的 hash 值即可。
0x01 代码实现
先 DFS 预处理所有的 hash 值。注意 hash 由于是对有序序列进行 hash 那么 hash值要对顺序变化铭感,可以采用类似于字符串 hash 的技巧,用一个大质数作为进制,自然溢出之类的。
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<bitset>
// #define ONLINE_JUDGE
#define INPUT_DATA_TYPE int
#define OUTPUT_DATA_TYPE int
INPUT_DATA_TYPE read(){register INPUT_DATA_TYPE x=0;register char f=0,c=getchar();while(c<'0'||'9'<c)f=(c=='-'),c=getchar();while('0'<=c&&c<='9')x=(x<<3)+(x<<1)+(c&15),c=getchar();return f?-x:x;}void print(OUTPUT_DATA_TYPE x){register char s[20];register int i=0;if(x<0){x=-x;putchar('-');}if(x==0){putchar('0');return;}while(x){s[i++]=x%10;x/=10;}while(i){putchar(s[--i]+'0');}return;}
std::map<unsigned long long,std::map<unsigned long long,unsigned long long> > mp;
int n;
unsigned long long hash1[500010],hash2[500010],mod1=100000000000000003,mod2=1000000000000000003;
std::queue<int> Q;
std::bitset<500010> book;
std::vector<int> e[500010];
char s[500010];
void addEdge(int u,int v){
e[u].push_back(v);
return;
}
void dfs(int u){
register int v;
if(hash1[u]||hash2[u]) return;
hash1[u]=hash2[u]=mod1+mod2+1140514+10919810;
for(v=0;v<e[u].size();++v){
dfs(e[u][v]);
hash1[u]=hash1[e[u][v]]*mod1*1145141919819000+s[u]*(v+mod2)+hash1[u]*114514;
hash2[u]=hash2[e[u][v]]*mod2*114051410919819+(v+1)*(s[u]+mod1)+hash2[u]*1919810;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("name.in", "r", stdin);
freopen("name.out", "w", stdout);
#endif
register int u,v,res=0;
register char c;
n=read();
for(u=1;u<n;++u){
loop:c=getchar();
if(c<'A'||'Z'<c) goto loop;
s[u]=c;
v=read();
addEdge(u,v);
v=read();
addEdge(u,v);
v=read();
addEdge(u,v);
}
dfs(1);
Q.push(1);
while(!Q.empty()){
u=Q.front();
Q.pop();
for(auto v:e[u])
if(!book[v]){
book[v]=1;
if(!mp[hash1[v]][hash2[v]]) mp[hash1[v]][hash2[v]]=1,++res;
Q.push(v);
}
}
print(res+1);
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}