const int inf = 1<<30;
const int N = 1009;
int dp[N][N]; //dp[i][j] i依赖与j时的最优解
int w[N], d[N];
int dis[N][N]; //每两个节点之间的距离
int best[N]; //每个节点为根的子树的最优解 best[i] = min( dp[i][j] ) (1<=j<=n)
vector<pair<int, int> >v[N];
int n;
void dfs_dis(int root, int s, int pre, int dd) //求root到各个节点的距离
{
dis[root][s] = dd;
for(int i=0; i<v[s].size(); i++)
{
int ss = v[s][i].first;
if(ss==pre) continue;
int len = v[s][i].second;
dfs_dis(root, ss, s, dd+len);
}
}
void dfs(int s, int pre)
{
int i, j, ss;
for(i=0; i<v[s].size(); i++)
{
ss = v[s][i].first;
if(ss==pre) continue;
dfs(ss, s);
}
for(i=1; i<=n; i++) //s依赖于i节点
if(dis[s][i]<=d[s])
{
dp[s][i] = w[i]; //s依赖于i 所以i处建站
for(j=0; j<v[s].size(); j++)
{
ss = v[s][j].first;
if(ss==pre) continue;
dp[s][i] += min( dp[ss][i] - w[i], best[ss] ); //如果ss也依赖于i则减去一个w[i]
}
best[s] = min(best[s], dp[s][i]);
}
}
int main()
{
int tt, i, j, a, b, c;
scanf("%d", &tt);
while(tt--)
{
scanf("%d", &n);
for(i=1; i<=n; i++) scanf("%d", &w[i]);
for(i=1; i<=n; i++) scanf("%d", &d[i]);
for(i=1; i<=n; i++) v[i].clear();
for(i=1; i<=n; i++) best[i] = inf;
for(i=1; i<=n; i++) for(j=1; j<=n; j++) dp[i][j] = inf;
for(i=1; i<n; i++)
{
scanf("%d%d%d", &a, &b, &c);
v[a].push_back( make_pair(b, c) );
v[b].push_back( make_pair(a, c) );
}
for(i=1; i<=n; i++) dfs_dis(i, i, 0, 0);
dfs(1, 0);
printf("%d\n", best[1]);
}
return 0;
}
POJ-2152-treeDP
最新推荐文章于 2022-11-21 16:51:26 发布