题目链接:https://cn.vjudge.net/problem/HDU-6201

题意:给你n个城市,n-1条道路,商人从某个城市买书,去某个城市卖书(两个城市可以相同)  每个城市的书的价格为ai  每条道路的花费为zi 

求商人的买卖书的最大收益是多少

思路 :  由于可以选择任意一个城市  买书,枚举每个城市 肯定会爆,所以就想到了 加一个原点0,0号城市与其他n个城市修路,路的花费设置为每个城市的书的价格,即代表了走到某个城市即花费了ai  yuan 来买书。

这样跑一遍单源最短路,dis数组存的就是从某个点出发  到另一个点的花费+买书的钱, 求最大收益,用 在某个城市卖书的钱  - dis[i]  最后取最大值。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
#define ll long long
#define pb push_back
#define mk make_pair
#define INF 0x3f3f3f3f
const int maxn = 1e5 + 5;

int T,n,m,a[maxn],dis[maxn];
bool vis[maxn];
vector<pair<int,int> > v[maxn],vv;
struct node {
    int x;
    ll w;
    node(){}
    node(int xx,ll ww):x(xx),w(ww){}
    const bool operator<(const node &aa)const{
        return w>aa.w;
    }
};
void dj(int st) {
    priority_queue<node> q;
    q.push(node(st,0));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)dis[i] = INF;
    dis[st]=0;
    while(!q.empty()) {
        node x = q.top();
        int fa = x.x;
        q.pop();
        if(vis[fa])continue;
        vis[fa]=1;
        for(int i=0;i<v[fa].size();++i) {
            int to = v[fa][i].first;
            int ww = v[fa][i].second;
            if(dis[to]>dis[fa] + ww) {
                dis[to] = dis[fa] + ww;
                q.push(node(to,dis[to]));
            }
        }
    }
} 
int main()
{
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            v[0].pb(mk(i,a[i]));
            vv.pb(mk(a[i],i));
        }
        for(int i=0;i<n-1;i++) {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            v[x].pb(mk(y,z));
            v[y].pb(mk(x,z));
        }
        dj(0);
        int ans = -INF;
        for(int j=1;j<=n;j++) {
            ans = max(ans, -dis[j] + a[j]);
        }
        printf("%d\n",ans);
        for(int i=0;i<=n;i++)v[i].clear();
    }
    return 0;
}