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[N]; ll w[N],xa[N]; int p[N],du[N],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; }