题目链接: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;
}