poj 2152 Fire dp 树形dp+暴力 ★★


Fire
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 1402   Accepted: 747

Description

Country Z has N cities, which are numbered from 1 to N. Cities are connected by highways, and there is exact one path between two different cities. Recently country Z often caught fire, so the government decided to build some firehouses in some cities. Build a firehouse in city K cost W(K). W for different cities may be different. If there is not firehouse in city K, the distance between it and the nearest city which has a firehouse, can’t be more than D(K). D for different cities also may be different. To save money, the government wants you to calculate the minimum cost to build firehouses.

Input

The first line of input contains a single integer T representing the number of test cases. The following T blocks each represents a test case. 

The first line of each block contains an integer N (1 < N <= 1000). The second line contains N numbers separated by one or more blanks. The I-th number means W(I) (0 < W(I) <= 10000). The third line contains N numbers separated by one or more blanks. The I-th number means D(I) (0 <= D(I) <= 10000). The following N-1 lines each contains three integers u, v, L (1 <= u, v <= N,0 < L <= 1000), which means there is a highway between city u and v of length L. 

Output

For each test case output the minimum cost on a single line.

Sample Input

5
5
1 1 1 1 1
1 1 1 1 1
1 2 1
2 3 1
3 4 1
4 5 1
5
1 1 1 1 1
2 1 1 1 2
1 2 1
2 3 1
3 4 1
4 5 1
5
1 1 3 1 1
2 1 1 1 2
1 2 1
2 3 1
3 4 1
4 5 1
4
2 1 1 1
3 4 3 2
1 2 3
1 3 3
1 4 2
4
4 1 1 1
3 4 3 2
1 2 3
1 3 3
1 4 2

Sample Output

2
1
2
2
3

Source

POJ Monthly,Lou Tiancheng


题意:

n个城市,n-1条带权边构成一棵树。

每个城市x需要在离自己不超过D[x]的距离内有一个消防站。

消防站只能建造于城市之中。每个城市建立消防站的花费是W[x]。


问满足条件的最小花费。

(n<=1000)


解法:

因为兄弟子树之间互相关联,这个题 考虑在某个结点上 建消防站或者不建消防站 很难实施。


令dp[x][y]代表 城市x最近的消防站在城市y  。


如果y在子树x外,则y点的花费不予考虑,否则要考虑。这么做是为了方便树形dp解题的一般思路,即先考虑


子树再汇总子树信息来考虑根结点。


因为y在子树x内,可以看作是过去的,如果在子树x外,可以看作是未来的。


首先假如母结点为x,儿子为y1,y2,...,yn。


那么假如x依赖于其子树中但不为x的结点,比如说是y1子树中的k1。


那么dp[x][k1]= dp[y1][k1]+  min(  dp[y2][k1]  ,  min{dp[y2][k2]}  (k2在子树y2内) )+...


假如x依赖于子树x外某点,比如上方的某结点k。


那么dp[x][k]= min(dp[y1][k], min{dp[y1][k1]}  (k1在子树y1内)     )    +   ...


假如x依赖于x自身,就是说在x点建立消防站。


那么dp[x][k]=W[x]+ min(dp[y1][x], min{dp[y1][k1]}  (k1在子树y1内)     )    +   ...


这么做完全是因为一点 :充分利用了从某点x出发走出子树x必须经过它的父节点fa。


不管是到达  兄弟结点子树内一点  或者是  父结点 或 父结点子树外的点。


min{dp[y1][k1]}  (k1在子树y1内)    可以存到  best[y1]中。



综上所述:这个题目是树形dp再加上了一点暴力搜索的成分在里面。


#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
typedef long long ll;
typedef pair pii;
const int INF =0x3f3f3f3f;
const int maxn=1000    ;

int n,x,y,w;
int W[maxn+10],D[maxn+10];

int dp[maxn+10][maxn+10];
int pre[maxn+10],best[maxn+10];
struct Edge
{
    int to,w;
    Edge(){}
    Edge(int to,int w):to(to),w(w){}

};
vector G[maxn+10];
void findFireStation(int from,int nei,int x,int fa,int dis)
{

     if(nei==pre[from])//上方
     {
         dp[from][x]=0;
         for(int i=0;iD[from])  continue;
         findFireStation(from,nei,y,x,dis+w);

     }
}


void dfs(int x,int fa)
{
    pre[x]=fa;
    for(int i=0;i


你可能感兴趣的:(ACM_动态规划,树形dp)