pku 1635 Subway tree systems(树的同构,最小表示)

树的同构的判断,先用深搜得到以某个节点为起点的01表示,0表示往远离中心的节点走,1表示往靠近中心的节点走。

用了两种方法做。

1.把树去除根节点后,可以分成数棵子树。每个子树对应一个01串,然后用字符的比较函数排列这些01串。递归调用,得到树的一种最小表示。

下面的代码因为反复使用string,速度很慢很慢。

#include <string> #include <vector> #include <cmath> #include <queue> #include <algorithm> #include <iostream> using namespace std; string min_pre(string str)//必须保证str是树的表示。如果是str随机01序列,则下面的代码会出错,需要给出跳出的条件。 { int start=0,end; vector<string> box; string temp; int depth=0; for(int i=0;str[i];i++) { depth+=str[i]=='0'?1:-1;//0表示深度+1,1则表示深度-1 if(depth==0)//深度回到0,说明得到了一棵子树 { end=i; temp=string("0")+min_pre(str.substr(start+1,end-start+1-1))+string("1");//去掉子树首位的0和末位的1,往里走一层,递归寻找子树的最小表示 box.push_back(temp); start=end+1; } } sort(box.begin(),box.end()); string ret; for(int p=0;p<box.size();p++) ret+=box[p]; return ret;//返回最小表示 } int main() { int T; scanf("%d",&T); string s1,s2; for(int t=0;t<T;t++) { cin>>s1>>s2; s1=min_pre(s1); s2=min_pre(s2); if(s1==s2) printf("same/n"); else printf("different/n"); } return 0; }

2.无回路的图,选定根节点,即可确定一棵树。一棵树统计每个节点的子节点个数,每个节点的深度,最后给每个节点排序,即可当成树的最小表示。最小表示相同的树同构。

#include <iostream> using namespace std; const int maxn=3005; struct node { int depth,son; }tree[maxn],tree2[maxn]; int CMP(const void* a,const void* b) { node* p=(node*)a; node* q=(node*)b; if(p->depth==q->depth) return p->son-q->son; else return p->depth-q->depth; } int min_pre(char str[],node result[])//无回路的图,选定根节点,即可确定一棵树。一棵树统计每个节点的子节点个数,每个节点的深度,最后排序,即可当成树的最小表示。最小表示相同的树同构。 { int node_num=1,now=0; int father[maxn]; father[0]=result[0].son=result[0].depth=0; for(int i=0;str[i];i++) { if(str[i]=='0') { father[node_num]=now; result[node_num].depth=result[father[node_num]].depth+1; result[node_num].son=0; now=node_num++; } else { result[father[now]].son+=result[now].son+1; now=father[now]; } } qsort(result,node_num,sizeof(result[0]),CMP); return node_num; } int main() { char str[maxn]; int T; scanf("%d",&T); for(int t=0;t<T;t++) { scanf("%s",str); int num=min_pre(str,tree); scanf("%s",str); int num2=min_pre(str,tree2); if(num!=num2) { printf("different/n"); continue; } int i; for(i=0;i<num;i++) { if(tree[i].depth!=tree2[i].depth||tree[i].son!=tree2[i].son) { printf("different/n"); break; } } if(i>=num) printf("same/n"); } return 0; }

你可能感兴趣的:(String,struct,tree,stdstring)