KUPC 2014 F - テレパシー

問題

二次元平面上にn匹きつねがいて、
位置が(x[i], y[i]), パワーがd[i].
(何度でも)i番目のきつねにコスト1を支払うとそのきつねのパワーを1上げることができる。


きつねi, jは(iのパワー)+(jのパワー)がi, jのユークリッド距離以上ならば通信できる。
直接通信したいきつね同士のグラフが、無向木で与えられるとき、
支払わなければならないコストの和の最小値を求めよ。

制約条件

n≦1000
座標の絶対値≦1000
d[i]≧0

方針

きつね間の距離は3000未満なので、一匹につき3000あげれば十分。
なので、木DPで、dp[i][j]をi番目を根とする部分木を条件が満たされる状態にするために、
i番目のきつねにはコストj「以上」を支払うとするときのコストの和の最小値とする。


これを更新するDPがO(n * 3000)でできる。
(iにj支払うとき、k番目の子に払うコストはdist_k - j以上であるため、dp[子k][dist_k-j]だけを見ればよいから)

ソースコード

int n, x[1000], y[1000];
int c[1000], d[1000];
ll dp[1000][3000];

vector<vi> e;
int dist[1000][1000];

void rec(int cur, int p){
	rep(i, e[cur].size()) if(e[cur][i] != p){
		int to = e[cur][i];
		rec(to, cur);
		dist[cur][to] = ceil(hypot(x[cur] - x[to], y[cur] - y[to]));
		dist[cur][to] -= d[cur] + d[to];
	}
	
	rep(i, 3000){
		ll sum = (ll)c[cur] * i;
		rep(j, e[cur].size()) if(e[cur][j] != p){
			
			int to = e[cur][j];
			sum += dp[to][max(0, dist[cur][to] - i)];
		}
		dp[cur][i] = min(dp[cur][i], sum);
		if(i) dp[cur][i] = min(dp[cur][i], dp[cur][i - 1] + c[cur]);
	}
	for(int i = 2999; i > 0; i--) dp[cur][i - 1] = min(dp[cur][i - 1], dp[cur][i]);
}

int main(){
	cin >> n;
	e.resize(n);
	
	rep(i, n) cin >> x[i] >> y[i];
	rep(i, n) cin >> d[i] >> c[i];
	rep(i, n - 1){
		int a, b; cin >> a >> b;
		a--; b--;
		e[a].pb(b);
		e[b].pb(a);
	}
	
	rep(i, n) rep(j, 3000) dp[i][j] = 1e18;
	rec(0, 0);
	
	
	ll ans = 1e18;
	rep(i, 3000) ans = min(ans, dp[0][i]);
	cout << ans << endl;
	
	return 0;
}