fire poj-2152

    题目大意:给出一颗树,给出两个相邻节点的距离,以及每个节点的接受范围,还有当前节点的代价。我们想要求出覆盖整个图的最小代价。

    注释:一个点被覆盖,当且仅当该点有防火站或者这个点的接受范围之内有防火站。计算两个不相邻节点的距离用LCA计算。节点数<=1000,接受范围<=10,000.

      想法:poj最后一道树形dp,用这道神一样的树形dp结尾,在好不过。

      对于一个节点来讲设几个状态:ans[pos]表示使以pos为根的子树被保护的最小代价。dp[pos][save]表示以pos为根的子树被保护的最小代价且pos节点必须被save节点保护。dist[i][j]表示i到j的距离。cost[i]表示在该节点建立防火站的代价。d[i]表示该节点的接受范围。

      然后,我们考虑神奇的转移:$dp[u][v]=cost[v]+\sum min(dp[k][v]-cost[v],ans[k])$。这个状态的充要条件是k也可以被v覆盖。如果不然,我们就直接将dp[u][v]+=ans[k]。

    最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define N 2100
using namespace std;
const int inf=1e9;
int cost[N],d[N],n;
int dist[N][N];
int val[N];
int dp[N][N];
int head[N];
int ans[N];
int to[N];
int nxt[N];
int tot;
queue<int>q;
inline void add(int x,int y,int z)
{
	to[++tot]=y;
	val[tot]=z;
	nxt[tot]=head[x];
	head[x]=tot;
}
void get_dist(int dist[],int s)
{
	dist[s]=0;
	q.push(s);
	while(q.size())
	{
		int u=q.front(); q.pop();
		for(int i=head[u];i;i=nxt[i])
		{
			int v=to[i];
			if(!dist[v]&&v!=s)
			{
				dist[v]=dist[u]+val[i];
				q.push(v);
			}
		}
	}
}
void dfs(int pos,int fa)
{
	for(int i=head[pos];i;i=nxt[i])
	{
		if(to[i]==fa) continue;
		dfs(to[i],pos);
	}
	for(int v=1;v<=n;v++)
	{
		if(dist[pos][v]<=d[pos])
		{
			int temp=0;
			for(int i=head[pos];i;i=nxt[i])
			{
				int k=to[i];
				if(k==fa) continue;
				temp+=min(dp[k][v]-cost[v],ans[k]);
			}
			dp[pos][v]=cost[v]+temp;
		}
		else dp[pos][v]=inf;
	}
	for(int i=1;i<=n;i++)
	{
		ans[pos]=min(ans[pos],dp[pos][i]);
	}
}
inline void original()
{
	tot=0;
	memset(head,0,sizeof head);
	memset(dp,0,sizeof dp);
	memset(dist,0,sizeof dist);
	memset(ans,63,sizeof ans);
}
int main()
{
	int cases;
	scanf("%d",&cases);
	while(cases--)
	{
		original();
		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]);
		}
		int a,b,c;
		for(int i=1;i<n;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			add(a,b,c);
			add(b,a,c);
		}
		for(int i=1;i<=n;i++)
		{
			get_dist(dist[i],i);
		}
		dfs(1,0);
		printf("%d\n",ans[1]);
	}
	return 0;
}

    小结:太tm神了。其中,计算节点距离的处理是很巧妙地... ...

[poj2152]fire_树形dp的更多相关文章

  1. POJ2152 Fire (树形DP)

    题意:n个城市n-1条边 组成一棵树 在每个城市修建消防站会有一个花费costi 每个城市能防火当且仅当地图上距离他最近的消防站距离小于di   问如何修建消防站 使地图上所有的城市都有预防火灾的能力 ...

  2. poj2152 Fire(树形DP)

    题目链接:https://vjudge.net/problem/POJ-2152 题意:给定一颗大小为n的树,在每个结点建消防站花费为w[i],如果某结点没有消防站,只要在它距离<=d[i]的结 ...

  3. 树形DP小结

    树形DP1.简介:树是一种数据结构,因为树具有良好的子结构,而恰好DP是从最优子问题更新而来,那么在树上做DP操作就是从树的根节点开始深搜(也就是记忆化搜索),保存每一步的最优结果.tips:树的遍历 ...

  4. 树形 DP 总结

    树形 DP 总结 本文转自:http://blog.csdn.net/angon823/article/details/52334548 介绍 1.什么是树型动态规划 顾名思义,树型动态规划就是在“树 ...

  5. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  6. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  7. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  8. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  9. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

随机推荐

  1. 使用Gulp进行代码压缩的步骤以及配置

    一.安装步骤 1.首先确定是否安装了node.js,如果未安装,请先安装node.js: 2.确定是否安装了包管理工具npm,如未安装请安装:npm install npm -g: 3.安装gulp: ...

  2. 吐血整理:人工智能PDF中文教材资源包2.73G基本包含全部学习资料-人工智能学习书单

    吐血整理:人工智能PDF中文教材资源包2.73G基本包含全部学习资料 人工智能学习书单(关注微信公众号:aibbtcom获取更多资源) 文末附百度网盘下载地址 人工神经网络与盲信号处理 人工神经网络与 ...

  3. 【BZOJ2882】工艺(后缀数组)

    [BZOJ2882]工艺(后缀数组) 题面 BZOJ权限题,我爱良心洛谷 题解 最容易的想法: 把字符串在后面接一份 然后求后缀数组就行了... #include<iostream> #i ...

  4. ZJOI2007仓库建设

    斜率优化 # include <stdio.h> # include <stdlib.h> # include <iostream> # include <s ...

  5. [BZOJ1014] [JSOI2008] 火星人prefix (splay & 二分答案)

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  6. IE浏览器右键菜单插件开发(上篇)——自定义一个IE右键菜单项

    要做一个IE右键浏览器插件,得3步走. 第一,在IE右键菜单上添加自定义菜单名称,是通过注册表实现的,如下: string regkey = @"Software\Microsoft\Int ...

  7. angular路由详解四(子路由)

    子路由是相对路由 路由配置部分: 主要是children const routes: Routes = [ {path:'home', component: HomeComponent, childr ...

  8. [Linux][Madplay播放器移植mini2440(ARM9)]

    Madplay移植到mini2440全过程详解 madplay交叉编译 交叉编译器:arm-linux-gcc 3.4.1PC环境:RedHat-6 注意:最好在root权限下执行以下移植,否则在ma ...

  9. iframe结构的项目,登录页面嵌套

    参考:http://www.cnblogs.com/qixin622/p/6548076.html 在网页编程时,我们经常需要处理,当session过期时,我们要跳到登陆页面让用户登陆,由于我们可能用 ...

  10. IIS前端页面不显示详细错误解决方法

    要想解决这个问题,有三种方法可以考虑: 1.Internet信息服务(IIS)管理器 2.Web.config文件 3. 命令行 在IIS的"错误页"右边的"编辑功能设置 ...