【題意】:給定一棵樹,給定邊權的區間[0,L],求最終樹的最長路<=S的概率; 

【題解】:武大校賽的樹dp,放了好久,看著題解勉強過了。只可以說我的樹dp太水了,還停留在背包的階段。
              設狀態dp[i][j]表示以i為根的子樹,其葉子結點到i的最長距離為j且該子樹最長路徑不超過s的概率。
              對于u的一個子樹v,先枚舉u連v的長度,然后再把之前的子樹和v這條鏈合并,好復雜,不會表達了,直接研究代碼吧。

【代碼】:
 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "algorithm"
 5 #include "vector"
 6 #include "queue"
 7 #include "cmath"
 8 #include "string"
 9 #include "cctype"
10 #include "map"
11 #include "iomanip"
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define fi first
16 #define se second
17 #define lc(x) (x << 1)
18 #define rc(x) (x << 1 | 1)
19 #define lowbit(x) (x & (-x))
20 #define ll long long
21 #define maxn 70
22 #define maxs 530
23 int n, l, s;
24 double dp[maxn][maxs];
25 double son[maxs], tmp[maxs];
26 double e;
27 vector<int> vec[maxn];
28 void dfs(int u, int fa) {
29     memset(dp[u], 0, sizeof(dp[u]));
30     dp[u][0] = 1.0;
31     int size = vec[u].size();
32     for(int i = 0; i < size; i++) {
33         int v = vec[u][i];
34         if(v == fa) continue;
35         dfs(v, u);
36         memset(son, 0, sizeof(son));
37         memset(tmp, 0, sizeof(tmp));
38         for(int j = 0; j <= l; j++)
39             for(int k = 0; k <= s; k++)
40                 if(j + k <= s)
41                     son[j+k] += e * dp[v][k];
42         for(int j = 0; j <= s; j++)
43             for(int k = 0; k <= s - j; k++)
44                 tmp[max(j, k)] += son[j] * dp[u][k];
45         for(int j = 0; j <= s; j++)
46             dp[u][j] = tmp[j];
47     }
48 }
49 
50 int main() {
51     int T, Case = 1;
52     scanf("%d", &T);
53     while(T--) {
54         scanf("%d%d%d", &n, &l, &s);
55         for(int i = 0; i <= n; i++) vec[i].clear();
56         e = 1.0 / (1.0 + l);
57         for(int i = 1; i < n; i++) {
58             int a, b;
59             scanf("%d%d", &a, &b);
60             vec[a].pb(b);
61             vec[b].pb(a);
62         }
63         dfs(1, -1);
64         double ans = 0.0;
65         for(int i = 0; i <= s; i++) ans += dp[1][i];
66         printf("Case %d: %.6f\n", Case++, ans);
67     }
68     return 0;
69 }
70