题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6201
题目描述: 有一棵节点的树, 每条边有权值, 可以任意选择起点和终点, 得到一个值 = 终点值 - 经过的边权值 - 起点值, 最大化这个值
解题思路: 我们先要求得的值是每个节点有书的时候的最小花费, 由于此最小花费可能是本节点买书, 也有可能是儿子买书, 现在我们将从叶子节点开始向上遍历, 这样只会使得所有的父子节点互相更新, 可是这个时候兄弟节点还没有更新, 所以我们做第二遍DFS由父节点更新子节点
代码:
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #include <set> #include <queue> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define mem0(a) memset(a,0,sizeof(a)) #define mem1(a) memset(a,-1,sizeof(a)) #define sca(x) scanf("%d",&x) #define de printf("=======\n") typedef long long ll; using namespace std; const int maxn = 1e5+100; int v[maxn]; int vis[maxn]; int cost[maxn]; int ans; vector<pair<int, int>> child[maxn]; void dfs1(int x) { vis[x] = 1; int len = (int)child[x].size(); cost[x] = v[x]; for( int i = 0; i < len; i++ ) { if( !vis[child[x][i].first] ) { dfs1(child[x][i].first); cost[x] = min( cost[x], cost[child[x][i].first]+child[x][i].second); } } } void dfs2(int x) { vis[x] = 1; int len = (int)child[x].size(); for( int i = 0; i < len; i++ ) { if( !vis[child[x][i].first] ) { if( cost[x] + child[x][i].second < cost[child[x][i].first] ) { cost[child[x][i].first] = cost[x] + child[x][i].second; dfs2(child[x][i].first); } } } ans = max( ans, v[x]-cost[x] ); } int main() { int t; scanf( "%d", &t ); while( t-- ) { int n; scanf( "%d", &n ); mem0(v); mem0(cost); for(int i = 1; i <= n; i++) { child[i].clear(); vis[i] = 0; } for( int i = 1; i <= n; i++ ) { scanf( "%d", v+i ); } for( int i = 1; i < n; i++ ) { int s, e, w; scanf( "%d%d%d", &s, &e, &w ); child[s].push_back(pair<int, int>(e,w)); child[e].push_back(pair<int, int>(s,w)); } ans = 0 ; dfs1(1); mem0(vis); dfs2(1); printf( "%d\n", ans ); } return 0; }
思考: 代码过不了, 现在已经十二点半了, 不改了, 睡了,通过这个意识到了自己树的薄弱, 以后要加强, 然后决定从现在开始就造轮子......搞一波儿事情了可以
时间: 2024-12-30 02:06:06