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: Accepted)

#include <iostream>
#include <map>
#include <cstring>
#include <vector>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

int N,T;

struct Edge{
	int a,b;
	long long t,m,v;
	Edge(){}
	Edge(int a,int b,long long t,long long m,long long v) : a(a), b(b), t(t), m(m), v(v) {}
};
vector<Edge> g[310];
vector<int> seg;
vector<int> rev;
int gen_seg(int x,int p){
	seg.push_back(x);
	rev.push_back(0);
	for(int i = 0 ; i < g[x].size() ; i++){
		if( g[x][i].b != p ) gen_seg(g[x][i].b,x);
	}
	if( p != -1 ) seg.push_back(p) , rev.push_back(1);
}
vector<int> pos[310];

vector<Edge> G[310];

long long dp[610][10010] = {};
long long dp2[10010] = {};

map< pair<int,int> , Edge > info;



int main(){
	for(int i = 0 ; i < 610 ; i++)
		for(int j = 0 ; j < 10010 ; j++)
			dp[i][j] = -1e12;
	
	cin >> N >> T;
	for(int i = 0; i < N-1 ; i++){
		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));
		info[make_pair(a,b)] = info[make_pair(b,a)] = Edge(a,b,t,m,v);
	}
	gen_seg(0,-1);
	/*for(int i = 0 ; i < seg.size() ; i++)
		cout << seg[i] << " ";
	cout << endl;
	for(int i = 0 ; i < rev.size() ; i++)
		cout << rev[i] << " ";
	cout << endl;
	*/
	for(int i = 0 ; i < seg.size() ; i++)
		pos[seg[i]].push_back(i);
	dp[0][0] = 0;
	for(int i = 0 ; i+1 < seg.size() ; i++){
		Edge e = info[make_pair(seg[i],seg[i+1])];
		/*for(int j = 0 ; j <= T ; j++){
			if( dp[i][j] >= 0 ) cout << "[" << i << "][" << j << "] = " << dp[i][j] << endl;
		}*/
		if( rev[i+1] ){
			for(int j = 0 ; j <= T ; j++){
				dp[i+1][j] = max(dp[i+1][j],dp[i][j]);
			}
		}else{
			// use
			long long m = e.m / 2, v = e.v * 2, t = e.t * 2;
			for(int j = 0 ; j <= T ; j++) dp2[j] = -1e12;
			if( m > 0 ){
				//ikkai ugoku
				m--;
				for(int j = t ; j <= T ; j++) dp2[j] = dp[i][j-t]+v;
				if(e.m%2){
					for(int j = T ; j >= 2*e.t ; j--){
						dp2[j] = max(dp2[j],dp2[j-2*e.t]+e.v);
					}
				}
			}else{
				// ikkai ugoku
				if(e.m%2)
					for(int j = 2*e.t ; j <= T ; j++) dp2[j] = dp[i][j-2*e.t]+e.v;
			}
			// muda ni move
			for(int j = t ; j <= T ; j++)
				dp2[j] = max(dp2[j],dp[i][j-t]);
				
			for(long long k = 1; m > 0 ; k *= 2 ){
				long long wei = min(m,k);
				long long VV = v * wei;
				long long TT = t * wei;
				for(int j = T ; j >= TT ; j--){
					dp2[j] = max(dp2[j],dp2[j-TT]+VV);
				}
				m -= wei;
			}
			
			for(int j = 0 ; j <= T ; j++)
				dp[i+1][j] = max(dp[i+1][j],dp2[j]);
			
			// unuse
			int next = *upper_bound(pos[seg[i]].begin(),pos[seg[i]].end(),i);
			for(int j = 0 ; j <= T ; j++){
				dp[next][j] = max(dp[next][j],dp[i][j]);
			}
		}
	}
	cout << *max_element(dp[seg.size()-1],dp[seg.size()-1]+T+1) << endl;
	
	
	
	
}