POI 2001 跳舞蝇
2016-03-13 21:27
323 查看
02年的论文题,论文里的方法看不懂QAQ。
然后07年的论文里有一个有向图的同构判定,于是拿来水一水。
结果……
呵呵呵呵呵呵呵呵呵
让我静一静TAT
我觉得肯定是评测机太慢了,我的复杂度是d*n*k的
昨天睡觉的时候突然想起来这个是基环内向树哎。
既然是这样的话我们当然不能用普通的图的hash了。
首先考虑树的部分,当然是有根树的hash了,这个很好搞。
然后设有根树的根在环上。
当然我们知道每条链的尽头都是环(自环也是环)
于是我们想一下环可以怎么hash。
环?循环?字符串的循环同构?(不要问我怎么想到的)
于是我们可以把环看成一个串,串上每个字符就是这个点所连的树的hash值。
然后对每个环求hash值。
最后排序一下比较所有环的hash值(一一对应)
啦啦啦啦啦啦啦啦啦了~
然后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; }
相关文章推荐
- 将博客搬至CSDN
- [RxJS] Basic DOM Rendering with Subscribe
- 快乐的JS正则表达式(开篇)
- 创建自定义控件
- 个人所得税
- C 语言基础(一)
- 线程和进程
- 有以下宏定义, #define MIN(A,B) ((A) <= (B) ? (A) : (B)) 请写出一种不能正确返回的情况?
- Develop -- Training(十二) -- 管理音频播放
- 第二次CCF计算机软件能力认证考试题解(Java)--201409--字符串匹配--100分通过
- TXT四则运算计算器
- 菜鸟入门--在linux下用vim编写一个C程序
- HDU 1872
- arcengine 创建mdb
- JS基础知识
- 使用宏定义写出swap(x,y)
- 博客开通的目的和想法
- 电面的题目分享
- iOS开发UI篇—核心动画(UIView封装动画)
- springMVC框架下JQuery传递并解析Json数据