【POJ 2152】 Fire

【题目链接】

             点击打开链接

【算法】

           同样是树形DP,但是比较难,笔者做这题看了题解

           令f[i][j]表示在以i为根的子树中

           1.在以i为根的子树中建一些消防站

           2.在节点j必须建一个消防站

           3.以i为根的子树中,每个节点在满足距离不超过D的前提下,选一个子树内的节点或节点j作为“负责站”

           4.节点i的负责站必须是节点j

           的最小代价

           考虑转移,为了转移方便,我们用一个辅助状态best[i]表示以i为根的子树中,每个节点在满足距离不超过D的前提下,

扫描二维码关注公众号,回复: 1015567 查看本文章

           选一个子树内的节点作为“负责站”的最小代价,显然 : best[i] = min{f[i][j]}(j在以i为根的子树中)

           当dis(i,j) > Di时,f[i][j] = +oo(正无穷,表示不存在这种状态

           当dis(i,j) <= Di时,它的每个子节点k有两种选择 :

           1.选择子树内的节点为“负责站”,代价为best[k]

           2.选择j为它的“负责站”,代价为f[k][j]

           因此f[i][j] = w[j] + sigma(min{best[k],f[k][j]}) (k为i的孩子)

           最后,best[1]就是答案 

【代码】

            

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>
using namespace std;
#define MAXN 1010
const int INF = 2e9;

int i,T,n,u,v,l;
vector< pair<int,int> > e[MAXN];
int dis[MAXN],best[MAXN],w[MAXN],d[MAXN],f[MAXN][MAXN];

inline void getdist(int x)
{
		int i,y;
		for (i = 0; i < e[x].size(); i++)
		{
				y = e[x][i].first;
				if (dis[y] == -1)
				{
						dis[y] = dis[x] + e[x][i].second;
						getdist(y);	
				}	
		}	
}
inline void dfs(int x,int fa)
{
		int i,j,y;
		for (i = 0; i < e[x].size(); i++)
		{
				y = e[x][i].first;
				if (fa != y) dfs(y,x);
		}	
		for (i = 1; i <= n; i++) dis[i] = -1;
		dis[x] = 0;
		getdist(x);
		best[x] = INF;
		for (i = 1; i <= n; i++) f[x][i] = INF;
		for (i = 1; i <= n; i++)
		{
				if (dis[i] <= d[x])
				{
						f[x][i] = w[i];
						for (j = 0; j < e[x].size(); j++)
						{
								y = e[x][j].first;
								if (fa != y) f[x][i] += min(best[y],f[y][i]-w[i]);	
						}	
						best[x] = min(best[x],f[x][i]);
				}
		}
}

int main() 
{
		
		scanf("%d",&T);
		
		while (T--)
		{
				scanf("%d",&n);
				for (i = 1; i <= n; i++) e[i].clear();
				for (i = 1; i <= n; i++) scanf("%d",&w[i]);
				for (i = 1; i <= n; i++) scanf("%d",&d[i]);
				for (i = 1; i < n; i++)
				{
						scanf("%d%d%d",&u,&v,&l);
						e[u].push_back(make_pair(v,l));
						e[v].push_back(make_pair(u,l));
				}	
				dfs(1,0);
				printf("%d\n",best[1]);
		}
		
		return 0;
	
}

猜你喜欢

转载自blog.csdn.net/even_bao/article/details/80329075