题目链接:
POJ 2152 Fire
题意:
给一个
数据范围:
分析:
点依赖型树形
首先对每个点
然后递归解决以
更新
总的时间复杂度:
陈启峰的”一张一弛,解题之道”论文
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long ll;
const int MAX_N = 1010;
const int inf = 0x3f3f3f3f;
int T,n,total;
int head[MAX_N],cost[MAX_N],limit[MAX_N],dis[MAX_N][MAX_N];
int dp[MAX_N][MAX_N],best[MAX_N];
struct Edge {
int v,w,next;
}edge[MAX_N * 2];
void AddEdge(int u,int v,int w)
{
edge[total].v = v;
edge[total].w = w;
edge[total].next = head[u];
head[u] = total++;
}
void dfs_dis(int u,int p,int root)
{
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v,w = edge[i].w;
if (v == p) continue;
dis[root][v] = dis[root][u] + w;
dfs_dis(v,u,root);
}
}
void wyr(int u,int p)
{
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if (v == p) continue;
wyr(v,u);
}
for (int i = 1; i <= n; ++i) {
if (dis[u][i] > limit[u]) continue;
dp[u][i] = cost[i];
//printf("dp[%d][%d] = %d\n",i,dp[u][i]);
for (int j = head[u]; j != -1; j = edge[j].next) {
int v = edge[j].v,w = edge[j].w;
if (v == p) continue;
dp[u][i] += min(dp[v][i] - cost[i],best[v]);
}
best[u] = min(best[u],dp[u][i]);
//printf("i = %d best[%d] = %d dp[%d][%d] = %d\n",best[u],dp[u][i]);
}
}
int main()
{
scanf("%d",&T);
while (T--) {
scanf("%d",&n);
for (int i = 1; i <= n; ++i) { scanf("%d",&cost[i]); }
for (int i = 1; i <= n; ++i) { scanf("%d",&limit[i]); }
total = 0;
memset(head,-1,sizeof(head));
for (int i = 1; i < n; ++i) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
AddEdge(u,w);
AddEdge(v,w);
}
memset(dis,0,sizeof(dis));
for (int i = 1; i <= n; ++i) { dfs_dis(i,i); }
memset(best,0x3f,sizeof(best));
memset(dp,sizeof(dp));
wyr(1,0);
printf("%d\n",best[1]);
}
return 0;
}