BZOJ4557 侦察守卫

题解:

和HDU5290很像,但是hdu挂了,等好了再来补这个题

不是太懂啊。。。

看了题解也不懂。。。。。

等做了HDU2590再来看看这题

代码:

//http://blog.csdn.net/aarongzk/article/details/51703297
//http://blog.csdn.net/ziqian2000/article/details/52334662

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define se second
#define fs first
#define LL long long
#define CLR(x) memset(x,0,sizeof x)
#define MC(x,y) memcpy(x,y,sizeof(x))
#define SZ(x) ((int)(x).size())
#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int> P;
const double eps=1e-9;
const int maxn=500100;
const int mod=1e9+7;
const int INF=1e9;

int w[maxn],b[maxn],head[maxn];
int down[maxn][25],up[maxn][25];
int n,d,k,cnt,q;

//down[i][j]表示以i为根的子树中,向下前j层的最小花费
//up[i][j]表示以i为根的子树中,向上j层被覆盖,其子树满足条件的最小花费 

struct Edge{
    int v,nxt;
}edge[maxn*2];

void AddEdge(int u,int v){
    edge[cnt].v=v;
    edge[cnt].nxt=head[u];
    head[u]=cnt++;
}

void dfs(int u,int fa){
    if(b[u]) down[u][0]=up[u][0]=w[u];
    for(int i=1;i<=d;i++) up[u][i]=w[u];
    up[u][d+1]=INF;
    for(int i=head[u];i!=-1;i=edge[i].nxt){
        int v=edge[i].v;
        if(v==fa) continue;
        dfs(v,u);
        for(int j=0;j<=d;j++) up[u][j]=min(up[u][j]+down[v][j],up[v][j+1]+down[u][j+1]);
        for(int j=d;j>=0;j--) up[u][j]=min(up[u][j],up[u][j+1]);
        down[u][0]=up[u][0];
        for(int j=1;j<=d;j++) down[u][j]+=down[v][j-1];
        for(int j=1;j<=d;j++) down[u][j]=min(down[u][j-1],down[u][j]);
    }
}

int main(){
    cnt=0;
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&d);
    for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%d",&q);
        b[q]=1;
    }
    for(int i=1;i<=n-1;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        AddEdge(x,y);AddEdge(y,x);
    }
    dfs(1,-1);
    printf("%d\n",down[1][0]);
    return 0;
}
时间: 2024-10-02 11:30:21

BZOJ4557 侦察守卫的相关文章

BZOJ4557 [JLoi2016]侦察守卫 【树形dp】

题目链接 BZOJ4557 题解 orz 比较难的树形dp 不过想想也还好 看数据猜状态,一维是点,一维是D 那么就先设\(f[i][j]\)表示\(i\)所在子树已处理完毕,还能向上[或向任意方向]覆盖\(j\)层的最小代价 考虑转移,会发现子树间会相互影响,一个子树用\(f[s][j + 1]\)更新了\(f[i][j]\),其它的子树就完全没必要再用\(f[s'][j + 1]\)去更新了,此时反而可以用\(f[i][j]\)来减少该子树付出的代价 所以我们设一个\(g[i][j]\)表示

bzoj4557【JZOI2016】侦查守卫

4557: [JLoi2016]侦察守卫 Time Limit: 20 Sec  Memory Limit: 256 MB Submit: 114  Solved: 70 [Submit][Status][Discuss] Description 小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的 .换句话说,游戏的地图是一棵有N个节点的树.游戏中有一种道具叫做侦查守卫,当一名玩家在一个点上放置侦 查守卫后,它可以监视这个点以及与这个点的距

4557: [JLoi2016]侦察守卫 树形dp

一道好题,但也是一道水题. 可怜yyl蒟蒻看了别人怎么开数组后还是不会写. orz各位大神. 接下来上大神的题解(注意不是我的): 比较简单的一个DPf[i][j]表示节点为i的子树向下j层以下需要被覆盖的节点已经被覆盖了的答案g[i][j]表示节点为i的子树,子树内需要被覆盖的几点已经被覆盖了,还可以向上覆盖j层的答案f[i][0]=g[i][0]然后正着反着取两遍最小值即可 接着yy应该可以出来了.感觉不难.就是想不到…………………….too young too simple 1 #incl

[JLOI2016/SHOI2016]侦察守卫(树形dp)

小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的.换句话说,游戏的地图是一棵有N个节点的树. 游戏中有一种道具叫做侦查守卫,当一名玩家在一个点上放置侦查守卫后,它可以监视这个点以及与这个点的距离在D以内的所有点.这里两个点之间的距离定义为它们在树上的距离,也就是两个点之间唯一的简单路径上所经过边的条数.在一个点上放置侦查守卫需要付出一定的代价,在不同点放置守卫的代价可能不同. 现在小R知道了所有B神可能会出现的位置,请你计算监视所有这些位

p3267 [JLOI2016/SHOI2016]侦察守卫

分析 g[x][i]表示x点向上i条边的所有关键点都被覆盖的代价 f[x][i]表示x点向下i条边有关键点未被覆盖的代价 转移即可 代码 #include<bits/stdc++.h> using namespace std; const int inf = 1e9+7; int n,m,d,w[500100],is[500100],f[500100][22],g[500100][22]; vector<int>v[500100]; inline void dfs(int x,in

今日份水题2018.11.2

这几天想突破一下树形DP,这也是高中时候一直没能搞定的. 今天先来两道简单的水一下. HDU2196 Computer 给一棵树,求树中每个点离其他点最远的距离.每个点第一遍DFS记录能达到的最远距离dp1[]和次远距离dp2[],之后第二遍dfs,每次先更新当前节点答案然后再向下搜.如果当前节点位于父节点答案所在链上,即dp1[j]+w[i,j]=dp1[i],此时又分两种情况1: dp1[j]<dp2[i]+w[i,j],则dp2[j]=dp1[j],dp1[j]=dp2[i]+w[i,j]

一类树上问题的总结

有时,我们会遇到这样的问题: 在一个树上选定一些点,每个点能覆盖一定范围的点--之类 比如: CF70E Information Reform P4845 LJJ爱数树 P3267 [JLOI2016/SHOI2016]侦察守卫 通常,我们有两种做法: 方法一:我们对于每个点,考虑距离它最近的被选点 需要先证明一个显然的结论:对于每个i,以i为最近点的j是一个连通块. 换句话说,如果距离a的最近被选点为i,距离b的最近被选点也是i,那么a到b的路径上的点的最近被选点都是i. 考虑一条链:设Ax是