货币兑换问题

x33g5p2x  于2022-07-10 转载在 其他  
字(1.9k)|赞(0)|评价(0)|浏览(288)

一 原问题链接

Currency Exchange - POJ 1860 - Virtual Judge

https://vjudge.net/problem/POJ-1860

二 输入和输出

1 输入

输入的第1行包含 4 个数字:N 表示货币类型的数量,M 表示交换点的数量,S 表示货币类型,V 表示货币数量。然后是 M 行,每行都包含 6 个数字,表示相应交换点的描述。数字由一个或多个空格隔开。

2 输出

如果可以增加财富,则输出“YES”,在其他情况下输出“NO”

三 输入和输出样例

1 输入样例

3 2 1 20.0

1 2 1.00 1.00 1.00 1.00

2 3 1.10 1.00 1.10 1.00

2 输出样例

YES

四 分析

从当前货币出发,走一个回路,赚到一些钱。因为走过的边是双向的,因此能走过去就一定能够走回来。只需要判断图中是否有正环,即使这个正环不包含 S 也没关系,走一次正环就能赚一些钱。

样例1,如下图所示,包含一个正环 2-3-2,每走一次就赚一些钱。

计算过程如下:
1-2:(20-1.00)*1.00=19.00

2-3 3-2:(19-1.00)*1.1.=19.80 (19.80-1.00)*1.10=20.68

2-3 3-2:(20.68-1.00)*1.10=21.648 (21.648-1.00)*1.1.=22.7128

2-1:(22.7128-1.00)*1.00=21.7128

五 算法设计

可采用 Bellman-Ford 算法,判断正环。用边松弛 n-1 次后,再执行一次,如果还可以松弛,则说明有环(是正环还是负环,主要取决于松弛条件)。注意:对双向边,边数是 2m 或使用边数计数器 cnt。

六 实现

  1. package graph.poj1860;
  2. import java.util.Scanner;
  3. public class Poj1860 {
  4. static node e[] = new node[210];
  5. static int n;
  6. static int m;
  7. static int s;
  8. static int cnt = 0;
  9. static double v;
  10. static double dis[] = new double[110];
  11. static {
  12. for (int i = 0; i < e.length; i++) {
  13. e[i] = new node();
  14. }
  15. }
  16. static void add(int a, int b, double r, double c) {
  17. e[cnt].a = a;
  18. e[cnt].b = b;
  19. e[cnt].r = r;
  20. e[cnt++].c = c;
  21. }
  22. static boolean bellman_ford() { // 判正环
  23. for (int i = 0; i < dis.length; i++) {
  24. dis[i] = 0;
  25. }
  26. dis[s] = v;
  27. for (int i = 1; i < n; i++) { // 执行 n-1次
  28. boolean flag = false;
  29. for (int j = 0; j < cnt; j++) // 注意:边数是 2m 或使用 cnt
  30. if (dis[e[j].b] < (dis[e[j].a] - e[j].c) * e[j].r) {
  31. dis[e[j].b] = (dis[e[j].a] - e[j].c) * e[j].r;
  32. flag = true;
  33. }
  34. if (!flag)
  35. return false;
  36. }
  37. for (int j = 0; j < cnt; j++) // 再执行1次,还能松弛说明有环
  38. if (dis[e[j].b] < (dis[e[j].a] - e[j].c) * e[j].r)
  39. return true;
  40. return false;
  41. }
  42. public static void main(String[] args) {
  43. int a, b;
  44. double rab, cab, rba, cba;
  45. Scanner scanner = new Scanner(System.in);
  46. n = scanner.nextInt();
  47. m = scanner.nextInt();
  48. s = scanner.nextInt();
  49. v = scanner.nextDouble();
  50. for (int i = 0; i < m; i++) {
  51. a = scanner.nextInt();
  52. b = scanner.nextInt();
  53. rab = scanner.nextDouble();
  54. cab = scanner.nextDouble();
  55. rba = scanner.nextDouble();
  56. cba = scanner.nextDouble();
  57. add(a, b, rab, cab);
  58. add(b, a, rba, cba);
  59. }
  60. if (bellman_ford())
  61. System.out.println("YES");
  62. else
  63. System.out.println("NO");
  64. }
  65. }
  66. class node {
  67. int a;
  68. int b;
  69. double r;
  70. double c;
  71. }

七 测试

相关文章