[ARC198D] Many Palindromes on Tree 题解
对于树上
题目的条件等价于限定了若干组 bool 数组记录一下),那么直接退出循环,这样时间复杂度就是
这里有一个坑点:判断点对是否被考虑过,千万不能直接判断并查集中它们是否在同一个集合中!因为可能有一条限制是 break 后,
知道了
所以总的时间复杂度
放代码:
#include<bits/stdc++.h>
#include<atcoder/all>
using namespace std;
typedef pair<int,int> pii;
const int B=6907;
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n,c=0; cin>>n;
vector<vector<int> > g(n);
for(int i=1;i<n;i++){
int u,v; cin>>u>>v;
g[--u].emplace_back(--v);
g[v].emplace_back(u);
}
vector nx(n,vector<pii>(n,make_pair(-1,-1)));
// 对应文章中的 next 数组
for(int r=0;r<n;r++){
vector<int> v;
auto dfs=[&](auto &&self,int u,int f)->void{
if(v.size()>2)nx[r][u]=make_pair(v[1],v[v.size()-2]);
for(int i:g[u])
if(i!=f)v.emplace_back(i),self(self,i,u),v.pop_back();
};
v={r},dfs(dfs,r,r);
} // dfs 求 next 的值
atcoder::dsu s(n);
vector b(n,vector<bool>(n));
// 标记一个点对是否被考虑过
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
char x; cin>>x;
if(i==j)continue;
if(x&1){
int u=i,v=j;
while(~u&&!b[u][v])
b[u][v]=true,s.merge(u,v),tie(u,v)=nx[u][v];
}
} // 往上跳 next,并查集维护合并
vector<int> ld(n);
for(int i=0;i<n;i++)
ld[i]=s.leader(i)+1;
vector h(n,vector<unsigned long long>(n));
for(int r=0;r<n;r++){
auto dfs=[&](auto &&self,int u,int f)->void{
for(int i:g[u])
if(i!=f)h[r][i]=h[r][u]*B+ld[i],self(self,i,u);
}; // 计算路径哈希
h[r][r]=ld[r],dfs(dfs,r,r);
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(h[i][j]==h[j][i])c++;
cout<<c<<endl;
return 0;
}