同构:对于两棵树A, B,如果能通过重新标号使得两棵树完全相同,则称树A和B同构
例一.Subway tree systems POJ - 1635
题意:给出两棵树的表示法(这道题01是标在边上的),判断两棵树是否同构
思路:把树的表示法变成最小表示法,看两棵树最小表示法是否一样
有根树同构,无非是把子树的顺序换了一下
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
string str1,str2;
string min_pre(string str)
{
vector<string> box;
string ret="";
int equal=0,st=0;
for(int i=0;i<str.size();i++)
{
if(str[i]=='0') equal++;
else equal--;
if(equal==0)
{
if(i-1>st+1)
{
box.push_back("0"+min_pre(str.substr(st+1,i-1-st))+"1");
}
else box.push_back("01");
st=i+1;
}
}
sort(box.begin(),box.end());
for(int i=0;i<box.size();i++) ret+=box[i];
return ret;
}
int main()
{
int ca;
scanf("%d",&ca);
while(cin>>str1>>str2)
{
if(min_pre(str1)==min_pre(str2)) printf("same\n");
else printf("different\n");
}
}
例二:Regular Forestation
题意:求一个点把无根树分成同构的多个部分
思路:无根树同构把树的重心当做树根(一棵树最多有两个重心)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e5+100;
int h[N],ne[N*2],ver[N*2],tot;
int size[N];
int minn=0x3f3f3f3f;
vector<int>v;
int a[5];int n;
void add(int a,int b)
{
ver[tot]=b;
ne[tot]=h[a];
h[a]=tot++;
}
void dfs2(int x,int fa)
{
size[x]=1;
for(int i=h[x];i!=-1;i=ne[i])
{
int y=ver[i];
if(y==fa) continue;
dfs2(y,x);
size[x]+=size[y];
}
}
void dfs(int x,int fa,int num)
{
size[x]=1;
int maxsize=0;
for(int i=h[x];i!=-1;i=ne[i])
{
int y=ver[i];
if(y==fa) continue;
dfs(y,x,num);
size[x]+=size[y];
maxsize=max(maxsize,size[y]);
}
maxsize=max(maxsize,num-size[x]);
if(minn==maxsize) v.push_back(x);
else if(minn>maxsize)
{
v.clear();
v.push_back(x);
minn=maxsize;
}
}
string get(int x,int fa,int st)
{
vector<string> vec;
for(int i=h[x];i!=-1;i=ne[i])
{
int y=ver[i];
if(y==st||y==fa) continue;
vec.push_back(get(y,x,st));
}
sort(vec.begin(),vec.end());
string ans="0";
for(int i=0;i<vec.size();i++)
{
ans+=vec[i];
}
ans+="1";
return ans;
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs(1,-1,n);
int len=v.size();
for(int i=0;i<len;i++)
{
a[i]=v[i];
}
int maxx=-1;
for(int g=0;g<len;g++)
{
int root=a[g];
string A,B,C;
A=B=C="";
bool ok=1;
int num=0;
for(int i=h[root];i!=-1;i=ne[i])
{
num++;
int y=ver[i];
v.clear();
minn=0x3f3f3f3f;
dfs2(y,root);
dfs(y,root,size[y]);
if(v.size()==1) v.push_back(v[0]);
if(i==h[root])
{
A=get(v[0],0,root);
B=get(v[1],0,root);
}
else
{
C=get(v[0],0,root);
if(C==A||C==B) continue;
C=get(v[1],0,root);
if(C==A||C==B) continue;
ok=0;
break;
}
}
if(ok&&num>1) maxx=max(maxx,num);
}
printf("%d\n",maxx);
}