题目大意:
就是给出从树的中心开始的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; }