题目链接: HDU 6201
题目大意
n个城市, n-1条道路, 给出每条道路的长度, 每公里路费1元, 第i个城市书的价格为pi, 一个商人, 从某个城市出发, 买一本书, 在到另一个城市卖出去, 求最多能赚多少钱
思路
建图, 最短路
设置一个超级源点S, 与每个城市建边, 权值为pi(这个城市书的价格), 和一个超级汇点T, 与每个城市建边, 权值为-pi, 再将有道路相连的城市建边, 权值为道路长度
最后S-T的最短路就是最大受益的负数
代码
1029MS 15944K 1177 B G++
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100, inf = 0x3f3f3f3f;
struct edge
{
int to, cost;
edge(int a, int b) { to = a, cost = b; }
edge(){}
};
vector<edge> G[maxn];
typedef pair<int, int> P;
int n, d[maxn];
void dij(int s)
{
priority_queue<P, vector<P>, greater<P>> que;
memset(d, inf, sizeof(d));
d[s] = 0;
que.push(P(0, s));
while(!que.empty())
{
P p = que.top(); que.pop();
int v = p.second;
if(d[v] < p.first) continue;
for(auto &e : G[v])
{
if(d[e.to] > d[v] + e.cost)
{
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to], e.to));
}
}
}
}
void addedge(int u, int v, int cost)
{
G[u].push_back(edge(v, cost));
}
int main()
{
int T;
for(scanf("%d", &T); T; --T)
{
scanf("%d", &n);
for(int i=0; i<=n+1; ++i) G[i].clear();
int s = 0, t = n+1;
for(int i=0; i<n; ++i)
{
int p;
scanf("%d", &p);
addedge(s, i+1, p);
addedge(i+1, t, -p);
}
for(int i=0; i<n-1; ++i)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
}
dij(s);
cout << -d[t] << endl;
}
return 0;
}