Guest User

Untitled

a guest
Aug 20th, 2018
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.46 KB | None | 0 0
  1. extern crate smallvec; // 0.6.3
  2.  
  3. trait ToZeroBased {
  4. fn to_zero_based(usize) -> usize;
  5. fn to_zero_based_pair(pair: (usize, usize)) -> (usize, usize) {
  6. let (a, b) = pair;
  7. (Self::to_zero_based(a), Self::to_zero_based(b))
  8. }
  9. }
  10.  
  11. struct ZeroBased;
  12. impl ToZeroBased for ZeroBased {
  13. fn to_zero_based(i: usize) -> usize { i }
  14. }
  15.  
  16. struct OneBased;
  17. impl ToZeroBased for OneBased {
  18. fn to_zero_based(i: usize) -> usize { i - 1 }
  19. }
  20.  
  21. use std::collections::HashMap;
  22. use smallvec::SmallVec;
  23.  
  24. type Weight = i32;
  25. const THRESHOLD: usize = 8;
  26. type Graph = Vec<SmallVec<[usize; THRESHOLD]>>;
  27.  
  28. fn tree_sum<I: ToZeroBased>(weights: &[Weight], edges: &[(usize, usize)]) -> Weight {
  29. let answers = &mut HashMap::new();
  30. let mut graph = vec![SmallVec::new(); weights.len()];
  31.  
  32. for &edge in edges {
  33. let (from, to) = I::to_zero_based_pair(edge);
  34.  
  35. graph[from].push(to);
  36. graph[to].push(from);
  37. }
  38.  
  39. tree_sum_recurrent(answers, weights, &graph, 0, 0)
  40. }
  41.  
  42. fn tree_sum_unilecs(weights: &[Weight], edges: &[(usize, usize)]) -> Weight {
  43. tree_sum::<OneBased>(weights, edges)
  44. }
  45.  
  46. fn tree_sum_recurrent(
  47. answers: &mut HashMap<usize, Weight>,
  48. weights: &[Weight],
  49. graph: &Graph,
  50. prev: usize,
  51. center: usize,
  52. ) -> Weight {
  53. if !answers.contains_key(&center) {
  54. let neighbors = graph[center].iter();
  55.  
  56. let without_center = neighbors.clone()
  57. .filter(|&&i| i != prev)
  58. .map(|&i| tree_sum_recurrent(answers, weights, graph, center, i))
  59. .sum();
  60.  
  61. let mut without_neighbors = 0;
  62. for &curr in neighbors.filter(|&&i| i != prev) {
  63. without_neighbors += graph[curr]
  64. .iter()
  65. .filter(|&&i| i != center)
  66. .map(|&i| tree_sum_recurrent(answers, weights, graph, curr, i))
  67. .sum::<Weight>();
  68. }
  69.  
  70. let with_center = weights[center] + without_neighbors;
  71.  
  72. answers.insert(center, std::cmp::max(with_center, without_center));
  73. }
  74.  
  75. answers[&center]
  76. }
  77.  
  78. fn main() {
  79. let weights = [2, 1, 1, 1];
  80. let edges = [(0, 1), (0, 2), (0, 3)];
  81. println!("{}", tree_sum::<ZeroBased>(&weights, &edges)); // 3
  82.  
  83. let weights = [1, 1, 0, 1];
  84. let edges = [(0, 1), (0, 2), (1, 3)];
  85. println!("{}", tree_sum::<ZeroBased>(&weights, &edges)); // 2
  86. }
  87.  
  88. #[test]
  89. fn unilecs_test_case() {
  90. let weights = [1, 1, 0, 1];
  91. let edges = [(1, 2), (1, 3), (2, 4)];
  92.  
  93. assert_eq!(tree_sum_unilecs(&weights, &edges), 2);
  94. }
  95.  
  96. #[test]
  97. fn greedy_algorithm_countercase() {
  98. /*
  99. * 1
  100. * |
  101. * 1 -- 2 -- 1
  102. */
  103.  
  104. let weights = [2, 1, 1, 1];
  105. let edges = [(0, 1), (0, 2), (0, 3)];
  106.  
  107. // Naive greedy algorithm would return wrong result `2`,
  108. // while the right answer in this case is `3`
  109. assert_eq!(tree_sum::<ZeroBased>(&weights, &edges), 3);
  110. }
  111.  
  112. #[test]
  113. fn returns_zero_for_all_negative_weights() {
  114. let weights = [-1, -1, -1];
  115. let edges = [(0, 1), (1, 2)];
  116.  
  117. assert_eq!(tree_sum::<ZeroBased>(&weights, &edges), 0);
  118. }
  119.  
  120. #[test]
  121. fn returns_positive_weight_for_the_only_positive_weight() {
  122. let weights = [-1, -1, -1, 1];
  123. let edges = [(0, 1), (1, 2), (2, 3)];
  124.  
  125. assert_eq!(tree_sum::<ZeroBased>(&weights, &edges), 1);
  126. }
  127.  
  128. #[test]
  129. fn stress_test() {
  130. const LEN: usize = 100;
  131. let weights = vec![1; LEN];
  132. let edges = (1..LEN).map(|i| (i - 1, i)).collect::<Vec<_>>();
  133.  
  134. assert_eq!(tree_sum::<ZeroBased>(&weights, &edges), (LEN as Weight) / 2);
  135. }
Add Comment
Please, Sign In to add comment