【转】HDU 6201 树形DP 或 最长路
来源:互联网 发布:淘宝客服是干嘛的 编辑:程序博客网 时间:2024/05/21 02:52
原文地址:http://blog.csdn.net/meopass/article/details/77983498
简略题意:
n个节点,n−1条边,每个节点有一个点权v[i],代表这个点的物品售价。
每条边有一个权值,代表走这条路的花费。问从任意一点购买,在任意一点卖出的最高收益是多少。
解法1:
因为我们不知道从哪点出发到哪点终止。因此虚拟一个起点,一个终点,起点连接所有的节点,权值为−v[i],代表买入的代价。
所有节点再连向终点,权值为v[i],代表卖出的收益。每条边的权值置为负,代表走这条路需要花费代价。跑一次最长路即可。
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 110000;int t;int n;int val[maxn];vector<pair<int, int>> G[maxn];int dp[maxn];int dis[maxn];int vis[maxn];void init() { for(int i = 0; i < maxn; i++) G[i].clear(); memset(dp, 0x3f3f3f3f, sizeof dp); memset(dis, -0x3f3f3f3f, sizeof dis); memset(vis, 0, sizeof vis);}void spfa() { dis[0] = 0; vis[0] = 1; queue<int> q; q.push(0); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i].first, w = G[u][i].second; if(dis[v] < dis[u] + w) { dis[v] = dis[u] + w; if(!vis[v]) { q.push(v); vis[v] = 1; } } } }}int main() { scanf("%d", &t); while(t--) { init(); scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &val[i]); G[0].push_back({i, -val[i]}); G[i].push_back({n+1, val[i]}); } for(int i = 1; i < n; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); G[u].push_back({v, -w}); G[v].push_back({u, -w}); } spfa(); cout<<dis[n+1]<<endl; } return 0;}
解法2:
显然这是一棵树,最优的答案必然是一个父亲节点到一个儿子节点,因此跑树形DP即可。
对于dp[u],代表当前在u节点,我们已经购买了一本书,所需要花费的最小代价。
显然dp[u]从子树节点转移过来,或者从父亲节点转移过来。
答案即为dp[i]+v[i],i∈[1,n]。
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 110000;int t;int n;int val[maxn];vector<pair<int, int>> G[maxn];int dp[maxn];void init() { for(int i = 0; i < maxn; i++) G[i].clear(); memset(dp, 0x3f3f3f3f, sizeof dp);}void dfs1(int u, int fa) { dp[u] = -val[u]; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i].first; int w = G[u][i].second; if(v == fa) continue; dfs1(v, u); } for(int i = 0; i < G[u].size(); i++) { int v = G[u][i].first; int w = G[u][i].second; if(v == fa) continue; dp[u] = max(dp[u], dp[v] - w); }}void dfs2(int u, int fa, int w) { if(fa != -1) { dp[u] = max(dp[u], dp[fa] - w); } for(int i = 0; i < G[u].size(); i++) { int v = G[u][i].first; if(v == fa) continue; dfs2(v, u, G[u][i].second); }}int main() { scanf("%d", &t); while(t--) { init(); scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &val[i]); for(int i = 1; i < n; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); G[u].push_back({v, w}); G[v].push_back({u, w}); } dfs1(1, -1); dfs2(1, -1, 0); int ans = 0; for(int i = 1; i <= n; i++) ans = max(ans, dp[i]+val[i]); cout<<ans<<endl; } return 0;}
以上为转载内容。
【总监】十二春秋之,3483099@qq.com;
【Master】zelo,616701261@qq.com;【运营】运维艄公,897221533@qq.com;
【产品设计】流浪猫,364994559@qq.com;【体验设计】兜兜,2435632247@qq.com;
【iOS】淘码小工,492395860@qq.com;iMcG33K,imcg33k@gmail.com;
【Android】人猿居士,1059604515@qq.com;思路的顿悟,1217022114@qq.com;
【Java】首席工程师MR_W,feixue300@qq.com;【测试】土镜问道,847071279@qq.com;
【数据】fox009521,42151960@qq.com;【安全】保密,你懂的。
- HDU 6201 树形DP 或 最长路
- 【转】HDU 6201 树形DP 或 最长路
- HDU 6201 transaction transaction transaction【树形DP||SPFA最长路】
- hdu 2196树形dp经典 树的最长路
- 树形DP HDU 6201
- hdu 6201 树形DP
- HDU 6201 树形DP
- HDU 6201 树形dp
- HDU 6201transaction 【树形DP】
- 树中最长路径 树形DP HDU 3534 Tree
- HDU 2196 树形DP + 节点到达的最长距离
- hdu 1224 最长路+dp
- Hdu 2196 Computer (树的直径 或 树形DP)
- HDU 1520 Anniversary party(DFS或树形DP)
- HDU-6201 transaction transaction transaction(树形dp)
- hdu 6201 transaction transaction transaction 树形dp
- hdu2196树形dp求任一点的最长路
- HDU - 4276(转树形dp)
- 一道奇怪的分治问题
- Git学习记录<2>
- 事务的隔离级别
- 【CUGBACM15级BC第四场 B】hdu 4932 Miaomiao's Geometry
- String类的基本原理
- 【转】HDU 6201 树形DP 或 最长路
- 51Nod 1019 逆序数
- MySQL对数据库的基本操作语句
- configparser
- python note_0914
- Java-多态
- nodejs 基础
- python cookies
- 美团校招 关灯问题&&7的倍数