洛谷P3354 河流

有点权边权的树,选出k个关键点,根必须选。每个点的贡献为点权 * 到最近的关键祖先的距离。求最小总贡献。

解:树形DP是最毒瘤的算法......

设fxij表示以x为根的子树中选了j个关键点,且x的最近关键祖先是它的i级祖先时的最小贡献。

初态:fxi0 = val[x] * dis(),fx01 = 0。

转移:注意到各个i之间是分层转移的,只有女儿i = 0的情况会转移到母亲的每个i。

于是先转移fy0r,再分层转移fyjr。每层是一个树上背包。

 1 #include <bits/stdc++.h>
 2 
 3 typedef long long LL;
 4 const int N = 110;
 5 
 6 struct Edge {
 7     int nex, v, len;
 8 }edge[N]; int tp;
 9 
10 int e[N], n, siz[N], fa[N], val[N], k;
11 LL f[N][N][N], temp[N][N], d[N];
12 
13 inline void add(int x, int y, int z) {
14     tp++;
15     edge[tp].v = y;
16     edge[tp].len = z;
17     edge[tp].nex = e[x];
18     e[x] = tp;
19     return;
20 }
21 
22 inline LL dis(int x, int t) {
23     int y = x;
24     for(int i = 1; i <= t; i++) {
25         y = fa[y];
26     }
27     return d[x] - d[y];
28 }
29 /*
30 2 1
31 1 0 2
32 1 0 3
33 ------------- 2
34 */
35 void DFS(int x) {
36     //printf("x = %d d[x] = %lld  fa[x] = %d \n", x, d[x], fa[x]);
37     siz[x] = 1;
38     for(int i = 1; i <= n; i++) {
39         f[x][i][0] = val[x] * dis(x, i);
40         //printf("f %d %d %d  = %lld = %d * %d\n", x, i, 0, f[x][i][0], val[x], dis(x, i));
41     }
42     f[x][0][1] = 0;
43     for(int i = e[x]; i; i = edge[i].nex) {
44         int y = edge[i].v;
45         //printf("%d -> %d \n", x, y);
46         d[y] = d[x] + edge[i].len;
47         DFS(y);
48         memcpy(temp, f[x], sizeof(f[x]));
49         memset(f[x], 0x3f, sizeof(f[x]));
50         for(int j = 0; j <= n; j++) { /// dis
51             for(int p = 1; p <= k; p++) {
52                 for(int r = 1; r <= p; r++) {
53                     //printf("r = %d -> %lld \n", r, temp[j][p - r] + f[y][0][r]);
54                     f[x][j][p] = std::min(f[x][j][p], temp[j][p - r] + f[y][0][r]); /// don't choose
55                 }
56                 //printf("1f %d %d %d =  %lld \n", x, j, p, f[x][j][p]);
57             }
58         }
59         for(int j = 0; j <= n; j++) {
60             for(int p = k; p >= 0; p--) {
61                 for(int r = 0; r <= p; r++) {
62                     f[x][j][p] = std::min(f[x][j][p], temp[j][p - r] + f[y][j + 1][r]); /// choose y
63                 }
64                 //printf("2f %d %d %d =  %lld \n", x, j, p, f[x][j][p]);
65             }
66         }
67         siz[x] += siz[y];
68     }
69     //printf("%d return \n", x);
70     return;
71 }
72 
73 int main() {
74     memset(f, 0x3f, sizeof(f));
75     scanf("%d%d", &n, &k);
76     n++; k++;
77     k = std::min(k, n);
78     for(int i = 2, x, y; i <= n; i++) {
79         scanf("%d%d%d", &val[i], &x, &y);
80         add(x + 1, i, y);
81         fa[i] = x + 1;
82     }
83 
84     DFS(1);
85 
86     printf("%lld\n", f[1][0][k]);
87     return 0;
88 }
AC代码

注意每次合并子树的时候,原来的值不能保留。保留下来的要加上fy0r

恶心死我了...

转载于:https://www.cnblogs.com/huyufeifei/p/10517880.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值