POJ 2152 Fire 树形dp 压行大法好

题意:在树上建消防站,给出树边的距离,给出每个点建消防站的花费和能覆盖的距离,要求建消防站覆盖整张图,问最小花费是多少。

  这题贪心?没法做。暴力枚举搜索,just wash wash and sleep!

  我们还是树形dp吧,其实n^2的树形dp我是之前没见过的,怎么搞?这里面蕴藏的东西还是很暴力的。。。

  我们这样,先搞出dis[x][y]表示点x到点y的距离!暴力就好。完了之后弄一个dp数组,dp[x][y]表示x点被y点覆盖的情况所得到的最优答案(这里面包括其子树的花费),然后转移时要枚举y判断能覆盖哪个x,对于能覆盖的x,求出y覆盖其子树的最优解,向dp[x][y]转移,最终转移给答案数组。这转移的时候情况要考虑周全,而且不要忘了将算重的花费删掉

  上代码吧。

以上。

//我佩服你沉着机灵有胆量 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#define ms(a,p) memset(a,p,sizeof(a))
using namespace std;
const int MAXN=2010;
struct node{
    int y,z,nxt;
}edge[MAXN*2];
int cost[MAXN],d[MAXN],dis[MAXN][MAXN];
int head[MAXN],dp[MAXN][MAXN],ans[MAXN];
int n,m,k,tot,indx=0,t;queue<int>q;
void add(int x,int y,int z){
    edge[++indx].y=y;edge[indx].z=z;
    edge[indx].nxt=head[x];head[x]=indx;
}
void getdis(int dis[],int s){
    dis[s]=0;q.push(s);
    while(q.size()){
        int x=q.front();q.pop();
        for(int i=head[x],y;i;i=edge[i].nxt)
        if(!dis[y=edge[i].y]&&y!=s)
            dis[y]=dis[x]+edge[i].z,q.push(y);
    }
}
void dyna_pro(int x,int fa){
    for(int i=head[x],y;i;i=edge[i].nxt)
    if((y=edge[i].y)!=fa) dyna_pro(y,x);
    for(int y=1,tmp=0;y<=n;y++,tmp=0)
    if(dis[x][y]<=d[x]){
        for(int i=head[x],k;i;i=edge[i].nxt){
            if((k=edge[i].y)!=fa) tmp+=min(dp[k][y]-cost[y],ans[k]);
        }
        dp[x][y]=cost[y]+tmp;
    }
    else dp[x][y]=1e9;
    for(int i=1;i<=n;i++) ans[x]=min(ans[x],dp[x][i]);
}
int main(){
    scanf("%d",&t);
    while(t--){
        indx=0;ms(head,0);ms(dp,0);ms(dis,0);ms(ans,0x3f);
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
        for(int i=1;i<=n;i++) scanf("%d",&d[i]);
        for(int i=1,x,y,z;i<=n-1;i++){
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);add(y,x,z);
        }
        for(int i=1;i<=n;i++) getdis(dis[i],i);
        dyna_pro(1,0);printf("%d\n",ans[1]);
    }
    return 0;
}
//竟敢在尹兄面前耍花枪! 
树形dp

 

posted @ 2018-07-20 16:58  杜宇一声  阅读(109)  评论(0编辑  收藏  举报