题目大意:
就是给出从树的中心开始的dfs序, 根据两个dfs序列判断两棵树是否同构
大致思路:
首先根据dfs一直是从树的中心开始的, 所以不用担心中心的问题, 用树的Hash的话当然可以做
另外一个思路是从中心开始的话用树的最小表示法来做, 就是对于子树的字符串表示取字典序排序后的序列, 这样也可以, 当时练练手了...
树的最小表示法可以参考这篇博客:戳我
代码如下:
树的Hash的做法:
Result : Accepted Memory : 796 KB Time : 16 ms
/*
* Author: Gatevin
* Created Time: 2015/7/31 10:09:08
* File Name: Sakura_Chiyo.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define hash hhhhhhh
#define maxn 3000
vector<int> G[maxn];
char s[maxn];
stack<int> S;
const lint A = 233, B = 23333, P = 30007, Q = 1e9 + 7;
lint hash[maxn];
int idx[maxn];
bool cmp(int x, int y)
{
return hash[x] < hash[y];
}
void dfs(int now, int fa)
{
int nex;
for(int i = 0, sz = G[now].size(); i < sz; i++) if((nex = G[now][i]) != fa)
dfs(nex, now);
if(G[now].size() == 1)
hash[now] = A*B % Q;
int num = 0;
for(int i = 0, sz = G[now].size(); i < sz; i++) if((nex = G[now][i]) != fa)
idx[num++] = nex;
sort(idx, idx + num, cmp);
hash[now] = A;
for(int i = 0; i < num; i++)
{
hash[now] *= P;
hash[now] ^= hash[idx[i]];
hash[now] %= Q;
}
hash[now] = hash[now]*B % Q;
return;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
for(int i = 0; i < 3000; i++) G[i].clear();
scanf("%s", s);
int len = strlen(s);
int cnt = 0;
S.push(cnt);
for(int i = 0; i < len; i++)
{
if(s[i] == '0')
{
G[S.top()].push_back(++cnt);
S.push(cnt);
}
else S.pop();
}
S.pop();//抛出中心点0
dfs(0, -1);
lint value1 = hash[0];
for(int i = 0; i < 3000; i++) G[i].clear();
scanf("%s", s);
len = strlen(s);
cnt = 0;
S.push(cnt);
for(int i = 0; i < len; i++)
{
if(s[i] == '0')
{
G[S.top()].push_back(++cnt);
S.push(cnt);
}
else S.pop();
}
S.pop();//抛出中心点0
dfs(0, -1);
if(hash[0] == value1)
puts("same");
else puts("different");
}
return 0;
}
树的最小表示法的做法:
Result : Accepted Memory : 1188 KB Time : 579 ms
/*
* Author: Gatevin
* Created Time: 2015/7/31 10:27:52
* File Name: Sakura_Chiyo.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
string s1, s2;
string minRepresent(string s)
{
vector<string> son;
string ret = "";
int cnt = 0, st = 0;
for(int i = 0, sz = s.length(); i < sz; i++)
{
if(s[i] == '0') cnt++;
else cnt--;
if(cnt == 0)//表明这一段是一棵子树
{
if(i - 1 > st + 1) son.push_back("0" + minRepresent(s.substr(st + 1, i - 1 - st)) + "1");
else son.push_back("01");
st = i + 1;
}
}
sort(son.begin(), son.end());//对子树的最小表示法排序
for(int i = 0, sz = son.size(); i < sz; i++) ret += son[i];
return ret;
}
int main()
{
ios::sync_with_stdio(0);
int T;
cin>>T;//话说这里我写成scanf("%d", &T);就Wrong Answer了什么情况....
while(T--)
{
cin>>s1>>s2;
if(minRepresent(s1) == minRepresent(s2))
puts("same");
else puts("different");
}
return 0;
}