1
0

CodeForces-835F.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. using int64 = long long;
  4. constexpr int64 NEG = numeric_limits<int64>::min() / 4;
  5. struct Summary {
  6. int64 left = NEG;
  7. int64 right = NEG;
  8. int64 best = NEG;
  9. };
  10. Summary combine(const Summary &a, const Summary &b) {
  11. if (a.left == NEG) return b;
  12. if (b.left == NEG) return a;
  13. return {max(a.left, b.left), max(a.right, b.right),
  14. max({a.best, b.best, a.left + b.right})};
  15. }
  16. struct SegmentTree {
  17. int size = 1;
  18. vector<Summary> tree;
  19. explicit SegmentTree(const vector<Summary> &values) {
  20. while (size < static_cast<int>(values.size())) size <<= 1;
  21. tree.assign(2 * size, {});
  22. for (int i = 0; i < static_cast<int>(values.size()); ++i) tree[size + i] = values[i];
  23. for (int i = size - 1; i > 0; --i) tree[i] = combine(tree[2 * i], tree[2 * i + 1]);
  24. }
  25. Summary query(int left, int right) const {
  26. Summary before, after;
  27. for (left += size, right += size; left < right; left >>= 1, right >>= 1) {
  28. if (left & 1) before = combine(before, tree[left++]);
  29. if (right & 1) after = combine(tree[--right], after);
  30. }
  31. return combine(before, after);
  32. }
  33. };
  34. int main() {
  35. ios::sync_with_stdio(false);
  36. cin.tie(nullptr);
  37. int n;
  38. cin >> n;
  39. struct Edge { int to; int64 weight; };
  40. vector<vector<Edge>> graph(n);
  41. vector<int> degree(n, 0);
  42. for (int i = 0; i < n; ++i) {
  43. int u, v;
  44. int64 w;
  45. cin >> u >> v >> w;
  46. --u; --v;
  47. graph[u].push_back({v, w});
  48. graph[v].push_back({u, w});
  49. ++degree[u]; ++degree[v];
  50. }
  51. queue<int> leaves;
  52. vector<char> on_cycle(n, true);
  53. for (int i = 0; i < n; ++i) if (degree[i] == 1) leaves.push(i);
  54. while (!leaves.empty()) {
  55. int v = leaves.front(); leaves.pop();
  56. on_cycle[v] = false;
  57. for (const Edge &edge : graph[v]) {
  58. if (--degree[edge.to] == 1) leaves.push(edge.to);
  59. }
  60. }
  61. vector<int64> height(n, 0);
  62. vector<int> parent(n, -2);
  63. int64 tree_diameter = 0;
  64. for (int root = 0; root < n; ++root) {
  65. if (!on_cycle[root]) continue;
  66. vector<pair<int, int>> order;
  67. vector<int> stack{root};
  68. parent[root] = -1;
  69. while (!stack.empty()) {
  70. int v = stack.back(); stack.pop_back();
  71. order.push_back({v, parent[v]});
  72. for (const Edge &edge : graph[v]) {
  73. if (on_cycle[edge.to] || edge.to == parent[v]) continue;
  74. parent[edge.to] = v;
  75. stack.push_back(edge.to);
  76. }
  77. }
  78. for (int index = static_cast<int>(order.size()) - 1; index >= 0; --index) {
  79. int v = order[index].first;
  80. int64 first = 0, second = 0;
  81. for (const Edge &edge : graph[v]) {
  82. if (on_cycle[edge.to] || parent[edge.to] != v) continue;
  83. int64 candidate = height[edge.to] + edge.weight;
  84. if (candidate > first) { second = first; first = candidate; }
  85. else if (candidate > second) second = candidate;
  86. }
  87. height[v] = first;
  88. tree_diameter = max(tree_diameter, first + second);
  89. }
  90. }
  91. int start = find(on_cycle.begin(), on_cycle.end(), true) - on_cycle.begin();
  92. vector<int> cycle;
  93. vector<int64> next_weight;
  94. int previous = -1, current = start;
  95. do {
  96. cycle.push_back(current);
  97. int next = -1;
  98. int64 weight = 0;
  99. for (const Edge &edge : graph[current]) {
  100. if (on_cycle[edge.to] && edge.to != previous) {
  101. next = edge.to;
  102. weight = edge.weight;
  103. break;
  104. }
  105. }
  106. next_weight.push_back(weight);
  107. previous = current;
  108. current = next;
  109. } while (current != start);
  110. int k = cycle.size();
  111. vector<int64> coordinate(2 * k, 0);
  112. for (int i = 1; i < 2 * k; ++i) {
  113. coordinate[i] = coordinate[i - 1] + next_weight[(i - 1) % k];
  114. }
  115. vector<Summary> values(2 * k);
  116. for (int i = 0; i < 2 * k; ++i) {
  117. int64 h = height[cycle[i % k]];
  118. values[i] = {h - coordinate[i], h + coordinate[i], NEG};
  119. }
  120. SegmentTree segment(values);
  121. int64 best_cycle_path = numeric_limits<int64>::max();
  122. for (int cut = 0; cut < k; ++cut) {
  123. best_cycle_path = min(best_cycle_path, segment.query(cut, cut + k).best);
  124. }
  125. cout << max(tree_diameter, best_cycle_path) << '\n';
  126. return 0;
  127. }