记忆化递归搜索,注意树的规模可能会很大(2m),用64位整数也需要边计算边取模以防止溢出。
http://acm.hdu.edu.cn/showproblem.php?pid=5401
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <map> 5 6 using namespace std; 7 typedef __int64 LL; 8 9 const LL M = 1e9 + 7; 10 const int maxn = 100; 11 int m; 12 LL a, b, c, d, l; 13 LL L[maxn], R[maxn]; 14 LL f[maxn], L1[maxn]; 15 LL g[maxn]; 16 int A[maxn], B[maxn]; 17 LL ms[maxn]; 18 19 map<LL, LL> map1[maxn]; 20 map<pair<LL, LL>, LL> map2[maxn]; 21 22 LL dis(LL tr, LL x, LL y){ 23 if(!tr || x == y) return 0; 24 if(x > y) swap(x, y); 25 if(map2[tr].count(make_pair(x, y))) return map2[tr][make_pair(x, y)]; 26 if(y < g[A[tr]]) return map2[tr][make_pair(x, y)] = dis(A[tr], x, y); 27 if(x >= g[A[tr]]) return map2[tr][make_pair(x, y)] = dis(B[tr], x - g[A[tr]], y - g[A[tr]]); 28 return map2[tr][make_pair(x, y)] = (dis(A[tr], x, L[tr]) + dis(B[tr], y - g[A[tr]], R[tr]) + L1[tr]) % M; 29 } 30 31 LL get(LL x, LL tr){ 32 if(!tr) return 0; 33 if(map1[tr].count(x)) return map1[tr][x]; 34 if(x < g[A[tr]]) 35 return map1[tr][x] = 36 (get(x, A[tr]) + get(R[tr], B[tr]) + ms[B[tr]] * (L1[tr] + dis(A[tr], L[tr], x))) % M; 37 return map1[tr][x] = 38 (get(x - g[A[tr]], B[tr]) + get(L[tr], A[tr]) + ms[A[tr]] * (L1[tr] + dis(B[tr], R[tr], x - g[A[tr]]))) % M; 39 } 40 41 void update(int u){ 42 L1[u] = l; 43 L[u] = c, R[u] = d; 44 A[u] = a, B[u] = b; 45 g[u] = g[a] + g[b]; 46 ms[u] = g[u] % M; 47 LL ans = 0; 48 ans += (ms[a] * ms[b]) % M * l + f[a] + f[b]; 49 ans %= M; 50 LL lhs = get(c, a); 51 LL rhs = get(d, b); 52 ans += (ms[a] * rhs + ms[b] * lhs) % M; 53 ans %= M; 54 printf("%I64d ", ans); 55 f[u] = ans; 56 } 57 58 int main(){ 59 // freopen("in.txt", "r", stdin); 60 while(~scanf("%d", &m)){ 61 for(int i = 0; i <= m; i++) map1[i].clear(); 62 for(int i = 0; i <= m; i++) map2[i].clear(); 63 ms[0] = g[0] = 1; 64 f[0] = 0; 65 for(int i = 1; i <= m; i++) scanf("%I64d%I64d%I64d%I64d%I64d", &a, &b, &c, &d, &l), update(i); 66 } 67 return 0; 68 }