【poj2152】【Fire】【树形dp】
来源:互联网 发布:手机运动软件 编辑:程序博客网 时间:2024/05/20 09:21
Fire
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 1161 Accepted: 595
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
题意:给定n个节点组成的树,树有边权.现在要在一些点上建立消防站,每个点建站都有个cost[i],如果不在当前的点上建站,也要依赖其他的消防站,并且距离不超过limit[i]。求符合上述条件的最小费用建站方案。n <= 1000.
这道题是一道比较神的树形dp,我是在看了陈启峰2006年的国家集训队论文才会的:《一张一弛,解题之道 ——“约制、放宽”方法在解题中的应用》
既然已经有论文了,我就简单的说一下吧:
作为正常的思路,我们维护best[i]表示节点在节点i时的最小花费。
但是我们发现这道题有一个比较麻(dan)烦(teng)的一点就是他还有一个限制。这样我们所想出的动规就比较难解决了。
那么我们可以想到这个限制其实就是要找到离节点i最近的消防站就可以了。
但是就是这样,我们还是比较难以写出这个转移方程来。。。
我们再进一步往后想,其实我们没有必要找到最近的那个节点,只需要知道在i的限制范围之内的消防站就好了。——这一步就是论文里所说的放宽要求。
首先我们先要知道一个性质:假设在p1—>pm这个序列上的所有城市的负责站都为pi节点,那么总有一个最优解满足上述的性质。
至于证明我就不在这里赘述了,大家去看论文吧。
假设我们已经得到了这个性质,纳闷我们可以保存这样一个数组
f[i][j]表示在节点i的时候选择j点作为节点i的负责站的最优值。
那么我们就可以将转移方程分为这么几个阶段:
①:当dis[i][j]>limit[i]时我们不需要去管他。
②:当dis[i][j]<=limit[i]时还可以分成这么几个阶段:
(1):当j不是i的子树的时候,那么i的子节点x就有两种选择,一个是选择x的子树中的消防站,那么f[i][j]=best[x]。另 一种就是选择在x外的节点作为负责站,呢们根据上面个的那个性质我们可以知道i的负责站跟x的一样,那么f[i][j]=f[x][j]。
f[i][j]+=min(f[x][j],best[x]);
(2):选择i节点建消防站。
f[i][i]+=cost[i]+min(best[x],f[x][i]);
(3):选择i节点的子树为负责站,其实这种情况跟第一种很像
f[i][j]+=min(f[k][i]-cost[j],best[k])+cost[j];
这样以后我们就可以求解了。
#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const int N=1010;const int inf=210000000;struct S{ int v,len;}point;vector <S> tr[N];int t,n,best[N],dis[N][N],f[N][N],cost[N],limit[N],now;/*------ 预处理两点之间的距离 --------*/ void dfs(int x,int last,int Len){ int i,j,v,len; dis[now][x]=Len; for(i=0;i<tr[x].size();++i){ v=tr[x][i].v; len=tr[x][i].len; if(v!=last) dfs(v,x,Len+len); }}void dp(int x,int last){ int i,j,v,len; for(i=0;i<tr[x].size();++i) if(tr[x][i].v!=last) dp(tr[x][i].v,x); for(i=1;i<=n;++i){ if(dis[x][i]<=limit[x]){ f[x][i]=cost[i]; for(j=0;j<tr[x].size();++j){ v=tr[x][j].v; len=tr[x][j].len; if(v!=last) f[x][i]+=min(f[v][i]-cost[i],best[v]); //第(2)、(3)种 } best[x]=min(best[x],f[x][i]); //第(1)种情况 } }}int main(){ scanf("%d",&t); while(t--){ int i,j,x,y,z; scanf("%d",&n); for(i=1;i<=n;++i) scanf("%d",&cost[i]); for(i=1;i<=n;++i) scanf("%d",&limit[i]); for(i=1;i<=n;++i){ tr[i].clear(); best[i]=inf; } for(i=1;i<=n;++i) for(j=1;j<=n;++j) f[i][j]=inf; for(i=1;i<n;++i){ scanf("%d%d%d",&x,&y,&z); point.v=y;point.len=z; tr[x].push_back(point); point.v=x;point.len=z; tr[y].push_back(point); } for(i=1;i<=n;++i){ now=i; dfs(i,0,0); } dp(1,0); printf("%d\n",best[1]); }}
- POJ2152 Fire 树形DP
- poj2152(Fire) 树形DP
- 【poj2152】【Fire】【树形dp】
- 【poj2152】Fire 树形DP
- 【POJ2152】Fire——树形DP
- POJ2152 树形DP
- POJ2152 Fire
- 树形dp(Fire)
- 【POJ 2152】Fire【树形DP】
- Fire - POJ 2152 树形dp
- poj 2152 Fire 树形dp
- poj 2152 Fire 树形DP
- 【树形DP】 POJ 2152 Fire
- [树形DP] POJ 2152 Fire
- Poj 2152 Fire (DP_树形DP)
- ***POJ 2152 - Fire(树形DP)
- poj 2152 Fire - 经典树形dp
- POJ 2152 Fire (树形DP,有趣)
- TCP/IP
- 机房收费系统重构(2)——未声明“ConfigurationManager”
- 编程之美15-彩色的树
- Linux-(10)Linux中的用户和组
- Hibernate中session的clear(),flush(),evict()方法详解
- 【poj2152】【Fire】【树形dp】
- 一个多月来的面试总结(阿里, 网易, 腾讯)
- Struts2 Result详解
- BZOJ3996【最小割】
- PowerDesigner 中的模型图介绍和建模顺序
- 3.0优化查询-引入视图
- 如何取得Android应用apk的UI资源和布局
- MYSQL 函数说明
- python模拟浏览器登陆人人网站