一、题目描述
C国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市。
任意两个城市之间最多只有一条道路直接相连。
这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为1条。
C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。
但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。
商人阿龙来到C国旅游。
当他得知“同一种商品在不同城市的价格可能会不同”这一信息之后,便决定在旅游的同时,利用商品在不同城市中的差价赚一点旅费。
设C国 n 个城市的标号从 1~n,阿龙决定从1号城市出发,并最终在 n 号城市结束自己的旅行。
在旅游的过程中,任何城市可以被重复经过多次,但不要求经过所有 n 个城市。
阿龙通过这样的贸易方式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品——水晶球,并在之后经过的另一个城市卖出这个水晶球,用赚取的差价当做旅费。
因为阿龙主要是来C国旅游,他决定这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。
现在给出 n 个城市的水晶球价格,m 条道路的信息(每条道路所连接的两个城市的编号以及该条道路的通行情况)。
请你告诉阿龙,他最多能赚取多少旅费。
注意:本题数据有加强。
输入格式
- 第一行包含 2 个正整数 n 和 m,中间用一个空格隔开,分别表示城市的数目和道路的数目。
- 第二行 n 个正整数,每两个整数之间用一个空格隔开,按标号顺序分别表示这 n 个城市的商品价格。
- 接下来 m 行,每行有 3 个正整数,x,y,z,每两个整数之间用一个空格隔开。
- 如果z=1,表示这条道路是城市 x 到城市 y 之间的单向道路;如果z=2,表示这条道路为城市 x 和城市 y 之间的双向道路。
输出格式
- 一个整数,表示答案。
数据范围
- 1≤n≤100000,
1≤m≤500000,
1≤各城市水晶球价格≤100
输入样例:
5 5
4 3 5 6 1
1 2 1
1 4 1
2 3 2
3 5 1
4 5 2
输出样例:
5
二、题解
题目大意:小龙到 C 国观光的同时顺便通过买卖当地珠宝赚取一些钱来减轻路由开销,C 国中有些城市之间是双向连接,有些是单向的,问小龙最多能赚多少。
假设 1~n 号城市的水晶球价格分别为 4,3,5,6,1。 阿龙可以选择如下一条线路:1->2->3->5,并在 2 号城市以 3 的价格买入水晶球,在 3 号城市以 5 的价格卖出水晶球,赚取的旅费数为 2。 阿龙也可以选择如下一条线路 1->4->5->4->5,并在第 1 次到达 5 号城市时以 1 的价格 买入水晶球,在第 2 次到达 4 号城市时以 6 的价格卖出水晶球,赚取的旅费数为 5。
方法一:2 × Dijkstra
思路
假如我是小龙,那么我很容易想到在最便宜的地方买,在价格最高的地方卖,但给定的图可能存在这种问题:就是说,我在某个地方低价买入之后,进入了一个价格相对较高但不是最高的城市,但是我进去之后回不了原来的城市了,但是原来的城市的下下个城市是最高的价格的,这样我就求不出最大收益了。
所以,跑一遍 Dijkstra 或 SPFA 解决不了全部样例。怎么做呢?
我的思路是:第一遍 Dijkstra 求出每个点到源点 1 的最小价钱,然后从第 n 个点为起点再跑一遍 Dijkstra,最后取最大值:dist2[1...V] - dist1[1...V]
。
可能存在的疑惑:
- Q1:为什么要跑第二遍呢?上面说了起点 1 能到的最便宜的地方,未必能到最鬼的地方,所以第二遍的意义是保证从
1 ---> cheapPos ---> luxuriousPos ---> V
是连通的,这样求出来的利润才会是合法的。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static int V, E, S;
static Edge[] edges1, edges2;
static int[] dist1, dist2;
static int[] head1, head2;
static boolean[] vis;
static int tot1, tot2;
static int INF = 0x3f3f3f3f;
static int[] p;
static int maxv = 100010, maxe = 500000 + 50;
private static void addEdge1(int u, int v) {
edges1[++tot1] = new Edge();
edges1[tot1].to = v;
edges1[tot1].next = head1[u];
head1[u] = tot1;
}
private static void addEdge2(int u, int v) {
edges2[++tot2] = new Edge();
edges2[tot2].to = v;
edges2[tot2].next = head2[u];
head2[u] = tot2;
}
static void dijkstra1() { //收购低价
vis = new boolean[maxv];
dist1 = new int[maxv];
S = 1;
Arrays.fill(dist1, INF);
dist1[S] = p[S]; //买入
Queue<Node> q = new PriorityQueue<>((e1, e2) -> e1.p - e2.p);
q.add(new Node(S, p[S]));
while (!q.isEmpty()) {
Node t = q.poll();
int v = t.id;
for (int i = head1[v]; i != 0; i = edges1[i].next) {
int to = edges1[i].to;
if (dist1[to] > dist1[v]) {
dist1[to] = Math.min(dist1[v], p[to]);
q.add(new Node(edges1[i].to, dist1[to]));
}
}
}
}
static void dijkstra2() { //收购低价
vis = new boolean[maxv];
dist2 = new int[maxv];
Queue<Node> q = new PriorityQueue<>((e1, e2) -> e2.p - e1.p);
S = V;
Arrays.fill(dist2, -INF);
dist2[S] = p[S]; //买入
q.add(new Node(S, p[S]));
while (!q.isEmpty()) {
Node t = q.poll();
int v = t.id;
for (int i = head2[v]; i != 0; i = edges2[i].next) {
int to = edges2[i].to;
if (dist2[to] < dist2[v]) {
dist2[to] = Math.max(dist2[v], p[to]);
q.add(new Node(edges2[i].to, dist2[to]));
}
}
}
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
V = sc.nextInt();
E = sc.nextInt();
p = new int[V+1];
for (int i = 1; i <= V; i++) {
p[i] = sc.nextInt();
}
edges1 = new Edge[2*maxe];
edges2 = new Edge[2*maxe];
head1 = new int[maxv];
head2 = new int[maxv];
for (int i = 0; i < E; i++) {
int from = sc.nextInt();
int to = sc.nextInt();
int z = sc.nextInt();
addEdge1(from, to);
addEdge2(to, from);
if (z == 2) {
addEdge1(to, from);
addEdge2(from, to);
}
}
dijkstra1();
dijkstra2();
int max = -INF;
for (int i = 1; i <= V; i++) {
max = Math.max(max, dist2[i] - dist1[i]);
}
System.out.println(max);
}
static class Node {
int id, p;
Node (int id, int p) {
this.id = id;
this.p = p;
}
}
static class Edge {
int to, next;
public Edge() {}
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,
方法二:分图层
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,