[poj 2152]Fire
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[poj 2152]Fire相关的知识,希望对你有一定的参考价值。
题目大意:给你一棵树,边上权值表示距离,一个点上可以建消防站,花费d[i]一个节点要么建消防站,要么周围dis[i]距离内必须有一个消防站,求覆盖全图的最小花费.
设f[i][j]为点i被火炉j控制的最优解.b[i]为点i最优方案.
\({b_i} = \min \{ {f_{i,j}}|j \in {s_i}\} \),{s_i}是i的儿子集合.
\({f_{i,j}} = {w_j} + \sum\limits_{k \in {s_i}} {\min \{ {b_k},{f_{k,j}} - {w_j}\} } \)
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #define N 1010 5 #define inf 0x2fffffff 6 #define __min(a,b) (((a)<(b))?(a):(b)) 7 int T,n,tot;int head[N],next[N << 1],to[N << 1],val[N << 1],cost[N],md[N],co[N],f[N][N],best[N],dis[N]; 8 void addedge(int u,int v,int w){next[tot] = head[u];to[tot] = v;val[tot] = w;head[u] = tot++;} 9 std::queue<int> q;int dist(int s) 10 { 11 memset(dis,-1,sizeof(dis));dis[s] = 0;q.push(s); 12 while(!q.empty()) 13 { 14 int v = q.front();q.pop();for(int i = head[v];~i;i = next[i]) 15 { 16 if(~dis[to[i]]) continue; 17 dis[to[i]] = dis[v] + val[i];q.push(to[i]); 18 } 19 } 20 } 21 void dfs(int u,int fa) 22 { 23 for(int i = head[u];~i;i = next[i]) if(to[i] != fa) dfs(to[i],u);dist(u); 24 best[u] = inf;for(int i = 0;i < n;i++) 25 { 26 if(dis[i] > md[u]) f[u][i] = inf; 27 else 28 { 29 f[u][i] = co[i];for(int j = head[u];~j;j = next[j]) if(to[j] != fa) f[u][i] += __min(best[to[j]],f[to[j]][i] - co[i]); 30 best[u] = __min(best[u],f[u][i]); 31 } 32 } 33 } 34 int main() 35 { 36 scanf("%d",&T);while(T--) 37 { 38 memset(head,-1,sizeof(head));scanf("%d\n",&n);for(int i = 0;i < n;i++)scanf("%d",&co[i]);for(int i = 0;i < n;i++)scanf("%d",&md[i]); 39 tot = 0;for(int i = 1,u,v,w;i < n;i++){scanf("%d %d %d",&u,&v,&w);addedge(u - 1,v - 1,w);addedge(v - 1,u - 1,w);} 40 dfs(0,-1);printf("%d\n",best[0]); 41 } 42 return 0; 43 }
以上是关于[poj 2152]Fire的主要内容,如果未能解决你的问题,请参考以下文章