Problem
给 n 个城市买卖书的价格
pricei
(同城买卖同价)。n-1 条双向路将 n 个城市连通,每条路径给定 x y z
,表示 x 与 y 城市道路的长度为 z 。每前进 1 km 的代价为 1 。求从一个城市买 1 本书再带到另一个城市卖出的最大收益。
Idea
多源最短路加超级源点 转化为 单源最短路。貌似这种题队友总喜欢拿网络流去套… 233.
从超级源点向每个城市 i 连一条边权为 pricei 的边,跑一发 Dijstra 可以得到每个城市的最短路(将其视作是拿一本书到达此地的最小费用,已包含买书及路程的费用)。
遍历 n 个点,将最短路与 pricei (此是视作卖书价格)作差求最大收益。
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 100000 + 10;
int T, n, pi[N];
long long dis[N];
struct Edge {
int nxt, to, val;
} e[N*2];
int head[N], cnt;
void addedge(int u, int v, int w) {
e[++cnt].nxt = head[u];
e[cnt].to = v;
e[cnt].val = w;
head[u] = cnt;
}
struct Node {
int idx;
long long dist;
} p, q;
bool operator<(Node a, Node b) {
return a.dist > b.dist;
}
void dijstra()
{
priority_queue<Node> que;
for(int i=1;i<=n;i++)
{
p.idx = i;
p.dist = pi[i];
que.push(p);
dis[i] = pi[i];
}
while(!que.empty())
{
p = que.top();
que.pop();
if(dis[p.idx] < p.dist) continue;
for(int i=head[p.idx];i;i=e[i].nxt)
{
q.idx = e[i].to;
q.dist = p.dist + e[i].val;
if(dis[q.idx] < q.dist) continue;
dis[q.idx] = q.dist;
que.push(q);
}
}
}
int main()
{
scanf("%d", &T);
while(T-- && scanf("%d", &n)!=EOF)
{
cnt = 0;
memset(head, 0, sizeof(head));
for(int i=1;i<=n;i++)
scanf("%d", &pi[i]);
for(int i=1, u, v, w;i<n;i++)
{
scanf("%d %d %d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
}
dijstra();
long long ans = 0;
for(int i=1;i<=n;i++)
ans = max(ans, pi[i] - dis[i]);
printf("%lld\n", ans);
}
}