您的位置:首页 > 其它

POI 2001 跳舞蝇

2016-03-13 21:27 323 查看
02年的论文题,论文里的方法看不懂QAQ。

然后07年的论文里有一个有向图的同构判定,于是拿来水一水。

结果……



呵呵呵呵呵呵呵呵呵

让我静一静TAT

我觉得肯定是评测机太慢了,我的复杂度是d*n*k的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef unsigned long long ll;
const int a=566;
const int b=346;
const int c=489;
ll f1[2005][55],f2[2005][55],s[2005];
int p1[2005],p2[2005],n;
void solve(ll f[2005][55],int p[2005],int k){
for(int i=1;i<=n;i++)s[i]=0;
for(int i=1;i<=n;i++){
f[i][k]=f[i][k-1]*a+f[p[i]][k-1]*b;
s[p[i]]+=f[i][k-1];
}
for(int i=1;i<=n;i++)
f[i][k]+=s[i]*c;
}
int t1[2005],t2[2005];
bool check(){
for(int i=1;i<=n;i++)
f1[i][0]=f2[i][0]=1;
for(int i=1;i<=33;i++){
solve(f1,p1,i);
solve(f2,p2,i);
for(int j=1;j<=n;j++){
t1[j]=f1[j][i];
t2[j]=f2[j][i];
}
sort(t1+1,t1+1+n);
sort(t2+1,t2+1+n);
for(int j=1;j<=n;j++)
if(t1[j]!=t2[j])return 0;
}
return 1;
}
int main(){
//freopen("a.in","r",stdin);
int T;scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&p1[i]);
for(int i=1;i<=n;i++)scanf("%d",&p2[i]);
puts(check()?"T":"N");
}
return 0;
}


昨天睡觉的时候突然想起来这个是基环内向树哎。

既然是这样的话我们当然不能用普通的图的hash了。

首先考虑树的部分,当然是有根树的hash了,这个很好搞。

然后设有根树的根在环上。

当然我们知道每条链的尽头都是环(自环也是环)

于是我们想一下环可以怎么hash。

环?循环?字符串的循环同构?(不要问我怎么想到的)

于是我们可以把环看成一个串,串上每个字符就是这个点所连的树的hash值。

然后对每个环求hash值。

最后排序一下比较所有环的hash值(一一对应)



啦啦啦啦啦啦啦啦啦了~

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef unsigned long long ll;
const int a=233;
const int b=213;
const int c=417;
const int N=2000+5;
vector<ll>v
;
ll w
,xa
;
int p
,du
,n;
void toposort(){
queue<int>q;
for(int i=1;i<=n;i++)
if(!du[i])q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
ll ans=0;
sort(v[u].begin(),v[u].end());
for(int i=0;i<v[u].size();i++)
ans=ans*a+v[u][i];
w[u]=ans+xa[v[u].size()+1];
du[p[u]]--;
v[p[u]].push_back(w[u]);
if(!du[p[u]])q.push(p[u]);
}
for(int i=1;i<=n;i++)
if(du[i]){
ll ans=0;
sort(v[i].begin(),v[i].end());
for(int j=0;j<v[i].size();j++)
ans=ans*a+v[i][j];
w[i]=ans+xa[v[i].size()+1];
w[i]+=c;
}
}
void findcircle(vector<ll>& g){
g.clear();
for(int i=1;i<=n;i++)
if(du[i]){
vector<ll>f;
int j=i;
do{
f.push_back(w[j]);
j=p[j];
}while(j!=i);
sort(f.begin(),f.end());
ll ans=0;
for(j=0;j<f.size();j++)
ans=ans*b+f[j];
g.push_back(ans);
}
sort(g.begin(),g.end());
}
vector<ll>f,g;
void init(){
for(int i=1;i<=n;i++){
v[i].clear();
du[i]=0;
}
}
int main(){
//freopen("a.in","r",stdin);
int T;scanf("%d",&T);
xa[0]=1;
for(int i=1;i<=2000;i++)xa[i]=xa[i-1]*a;
while(T--){
scanf("%d",&n);
init();
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
du[p[i]]++;
}
toposort();findcircle(f);
init();
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
du[p[i]]++;
}
toposort();findcircle(g);
puts(f==g?"T":"N");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: