Problem:
さんぽ

Problem Statement

ねこのそらは散歩が大好きだ．道を歩くと新しい発見がある．

そらの住む町は N 個の広場と N-1 本の道からなる．

道はちょうど二つの広場をつないでおり，枝分かれしたり道どうしが交わったりしない．

道には，歩くのにかかる時間 t，得られる発見の個数の上限 m，および，発見一つあたりの価値 v が指定されている．

道を一方の端からもう一方の端まで歩いたとき，m 回目までの通行では価値 v の発見が一つ得られるが，m+1 回目以降は発見が得られない．

今日もそらは，町内の散歩に出かけるようだ．

そらの散歩は広場 1 から始まり，いくつかの道 ( 0 本かもしれない ) を通って，最後に広場 1 に戻ってくる，というルートをとる．

また，日が暮れると寂しい気持ちになるので，そらは散歩時間を T 以下にしたいと思っている．

そらの友人であるあなたの仕事は，散歩時間が T 以下である散歩ルートにおいて，得られる発見の価値の総和の最大値を求めることである．

Input

入力は以下の形式に従う．与えられる数は全て整数である．

N T
a_1 b_1 t_1 m_1 v_1
. . .
a_{N-1} b_{N-1} t_{N-1} m_{N-1} v_{N-1}

入力の i+1 行目は，広場 a_i と b_i をつなぐ，通行時間 t_i，得られる発見の個数の上限 m_i，発見一つあたりの価値 v_i の道を表している．

Constraints

1 ≦ N ≦ 300

1 ≦ T ≦ 10^4

1 ≦ a_i, b_i ≦ N

1 ≦ t_i ≦ 10^4

0 ≦ m_i ≦ 10^4

1 ≦ v_i ≦ 10^5

どの二つの広場も道を通って行き来できる．

Output

得られる発見の価値の総和の最大値を 1 行に出力せよ．

Sample Input 1

4 5
1 2 1 4 7
2 3 1 2 77
2 4 1 2 777

Output for the Sample Input 1

1568

1→2→4→2→1 と移動することで，合計で価値 7+777+777+7=1568 の発見が得られる．

Sample Input 2

2 10000
1 2 1 10 1

Output for the Sample Input 2

10

Sample Input 3

5 15
1 2 3 2 1
2 3 3 2 1
1 4 8 2 777
1 5 1 3 10

Output for the Sample Input 3

32

Solution in C++ (judge verdict: Wrong Answer)

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const ll INF = 1000000000000000000LL;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
struct Edge{
  int src, dst, t, m, v;
  Edge(int s, int d, int t, int m, int v) : 
    src(s), dst(d), t(t), m(m), v(v) {}
};
typedef vector<Edge> Node;
typedef vector<Node> Graph;

Graph G;
int a[1000];
int t[1000], m[1000], vl[1000];
int prev[1000];
int last[1000];
void dfs(int v, int p, int& k){
  prev[k] = (last[v] >= 0) ? last[v] : k;
  last[v] = k;
  a[k++] = v;
  FORIT(e, G[v]){
    if(e->dst != p){
      t[k] = e->t;
      m[k] = e->m;
      vl[k] = e->v;

      dfs(e->dst, e->src, k);

      prev[k] = (last[v] >= 0) ? last[v] : k;
      last[v] = k;
      a[k++] = v;
    }
  }
}
void update(ll& x, ll y){
  if(x < y) x = y;
}

int main(){
  int N, T;
  while(cin >> N >> T){
    G = Graph(N);
    REP(i, N - 1){
      int a, b, t, m, v;
      cin >> a >> b >> t >> m >> v;
      a--; b--;
      G[a].push_back(Edge(a, b, t, m, v));
      G[b].push_back(Edge(b, a, t, m, v));
    }
    int K = 0;
    memset(last, -1, sizeof(last));
    memset(t, 0, sizeof(t));
    memset(m, 0, sizeof(m));
    memset(vl, 0, sizeof(vl));
    dfs(0, -1, K);
    static ll dp[610][10000] = {};
    REP(i, K) REP(j, T + 1) dp[i][j] = -INF;
    dp[0][0] = 0;
    /*
    for(int i = 1; i < K; i++){
      for(int u = 0; u <= T; u++){
        update(dp[i][u], dp[prev[i]][u]);
        if(u - 2 * t[i] >= 0) update(dp[i][u], dp[i - 1][u - 2 * t[i]]);
        for(int c = 2; c <= m[i]; c += 2){
          if(u - c * t[i] < 0) break;
          update(dp[i][u], dp[i - 1][u - c * t[i]] + c * vl[i]);
        }
        int mk = (m[i] + 1) / 2;
        if(m[i] % 2 == 1 && u - 2 * mk * t[i] >= 0) update(dp[i][u], dp[i - 1][u - 2 * mk * t[i]] + m[i] * vl[i]);
      }
    }
    */
    for(int i = 1; i < K; i++){
      if(m[i] >= 2){
        for(int u = 2 * t[i]; u <= T; u++) update(dp[i][u], dp[i - 1][u - 2 * t[i]] + 2 * vl[i]);
        ll rest = m[i] - 2;
        if(rest % 2 == 1) rest--;
        for(ll c = 2; rest >= 2; c <<= 1){
          ll mul = min(rest, c);
          for(int u = T; u >= mul * t[i]; u--) update(dp[i][u], dp[i][u - mul * t[i]] + mul * vl[i]);
          rest -= mul;
        }
      }
      if(m[i] % 2 == 1){
        int mk = (m[i] + 1) / 2;
        for(int u = 2 * mk * t[i]; u <= T; u++) update(dp[i][u], dp[i - 1][u - 2 * mk * t[i]] + m[i] * vl[i]);
      }
      if(m[i] == 0){
        for(int u = 2 * t[i]; u <= T; u++) update(dp[i][u], dp[i - 1][u - 2 * t[i]]);
      }
      for(int u = 0; u <= T; u++) update(dp[i][u], dp[prev[i]][u]); 
    }
    ll ans = 0;
    for(int i = 0; i <= T; i++) update(ans, dp[K - 1][i]);
    cout << ans << endl;
  }
  return 0;
}