POJ 3585 一道很好的树DP

题目要求给一棵加权无向树,求每个点到叶子节点的最大流量。范围20万。

必须是O(N)的树DP才行。

首先固定一个为根,做一次DFS,求每个节点到其子树的叶子节点的流量和son[i],以及每个节点对其父亲节点的贡献belong[i],还有每个点和他父亲节点的边权edge[i]。然后对每个节点做一次记忆化搜索,顺着第一次搜索的边反向搜索。DP的转移方程是

dp[i] = min(dp[father[i]] - belong[i], dege[i])  + son[i];

解题的过程比较坎坷。首先状态转移方程多次修改,导致第一次DFS所要求的东西不明确,所以改了好多次。这是写DP的一大忌讳……没确定转移过程就开始写题

确定转移方程以后,有一种特殊的情况没有处理好,就是当固定的根是个度为1的点时,需要特殊处理。思考问题需要群面。

一下为此题的代码:

ContractedBlock.gif ExpandedBlockStart.gif POJ 3585
  1 /*
2 * =====================================================================================
3 *
4 * Filename: dp.cpp
5 *
6 * Description: tree dp problem
7 *
8 * Version: 1.0
9 * Created: 2011年07月22日 13时41分18秒
10 * Revision: none
11 * Compiler: gcc
12 *
13 * Author: ronaflx
14 * Company: hit-ACM-Group
15 *
16 * =====================================================================================
17 */
18 #include <cstdlib>
19 #include <cctype>
20 #include <cstring>
21 #include <cstdio>
22 #include <cmath>
23 #include <ctime>
24 #include <climits>
25 #include <algorithm>
26 #include <functional>
27 #include <numeric>
28 #include <vector>
29 #include <map>
30 #include <set>
31 #include <queue>
32 #include <stack>
33 #include <bitset>
34 #include <list>
35 #include <string>
36 #include <iostream>
37 #include <sstream>
38 #include <fstream>
39 #include <iomanip>
40 #include <stdexcept>
41 #include <utility>
42 #include <cassert>
43 #include <complex>
44 using namespace std;
45 #define LEFT(i) ((i) << 1)
46 #define RIGHT(i) (((i) << 1) | 1)
47 #define MID(i) ((l[i] + r[i]) >> 1)
48 #define CC(i, v) memset(i, v, sizeof(i))
49 #define REP(i, l, n) for(int i = l;i < int(n);++i)
50 #define FOREACH(con, i) for(__typeof(con.begin()) i = con.begin();i != con.end();++i)
51 const int N = 200000;
52 const long long INF = (long long) N * N;
53 vector<pair<int, long long> > adj[N];
54 long long son[N], dp[N], belong[N], edge[N];
55 int father[N];
56 long long DP(int x)
57 {
58 if(x == -1) return 0;
59 if(dp[x] != - 1 && x != 0) return dp[x];
60 if(x == 0)
61 {
62 dp[x] = son[x];
63 if(adj[x].size() == 1) return adj[x][0].second * 2;
64 else return dp[x];
65 }
66 long long ans = (min(DP(father[x]) - belong[x], father[x] == -1 ? 0 : edge[x]) + son[x]);
67 dp[x] = ans;
68 return dp[x];
69 }
70 long long dfs(int x, int pre)
71 {
72 father[x] = pre;
73 int isLeaf = true;
74 FOREACH(adj[x], i)
75 {
76 if(i->first == pre) edge[x] = i->second;
77 else
78 {
79 isLeaf = false;
80 int score = min(i->second, dfs(i->first, x));
81 son[x] += score;
82 belong[i->first] = score;
83 }
84 }
85 return (isLeaf ? edge[x] : son[x]);
86 }
87
88
89 int main()
90 {
91 int t, n, v, u, c;
92 scanf("%d", &t);
93 while(t--)
94 {
95 scanf("%d", &n);
96 for(int i = 0;i < n;i++) adj[i].clear();
97 CC(son, 0);
98 CC(dp, -1);
99 for(int i = 1;i < n;i++)
100 {
101 scanf("%d%d%d", &v, &u, &c);
102 v--, u--;
103 adj[v].push_back(make_pair(u, (long long)c));
104 adj[u].push_back(make_pair(v, (long long)c));
105 }
106 dfs(0, -1);
107 for(int i = 0;i < n;i++)
108 DP(i);
109 // for(int i = 0;i < n++) printf("%lld %d %lld\n", son[i], father[i], dp[i]);
110 printf("%lld\n", *max_element(dp, dp + n));
111 }
112 return 0;
113 }

转载于:https://www.cnblogs.com/ronaflx/archive/2011/07/22/2114219.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值