• POJ 3662 Telephone Lines 二分,最小化第k大的数


    一、题目大意

    我们有n个点,p条边,最小化从1到n之间的路径的第k+1大的数(当路径不超过k时就是0)

    二、解题思路

    我们首先用dijkstra过一遍,判断从1能不能到n,不能直接输出-1结束。

    1能到达n的话,就对二分第k+1大的边进行二分,left选-1,right选最大的边的长度+1(这里我left一开始选取的时最小边-1,后来发现当k比较大时结果可能是0)

    二分的依据如下

    1. 设二分的值为mid
    2. 记录从1到n的路径中必走的大于mid的值的数量
    3. 如果超过了k,那么放大mid
    4. 如果小于等于k,那么缩小mid,同时记录
    5. 这样不断循环,直到找到一个临界值limit
    6. 当mid=limit时,大于mid的边小于等于k个
    7. 当mid=limit-1时,大于mid的边超过k个
    8. 那么limit一定就是第k+1大的边
    9. 输出最后一个(大于mid的边数小于等于k的)mid即可

    三、代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. typedef pair<int, int> P;
    7. vector

      edges[1007];

    8. bool used[1007];
    9. int n, p, k, d[1007], inf = 0x3f3f3f3f, maxt = 0;
    10. void input()
    11. {
    12. int from, to, cost;
    13. scanf("%d%d%d", &n, &p, &k);
    14. for (int i = 0; i < p; i++)
    15. {
    16. scanf("%d%d%d", &from, &to, &cost);
    17. edges[from - 1].push_back(P(cost, to - 1));
    18. edges[to - 1].push_back(P(cost, from - 1));
    19. maxt = max(cost, maxt);
    20. }
    21. }
    22. bool judgeByDijkstra(int mid)
    23. {
    24. for (int i = 0; i < n; i++)
    25. {
    26. d[i] = inf;
    27. used[i] = false;
    28. }
    29. d[0] = 0;
    30. priority_queue, greater

      > que;

    31. que.push(P(d[0], 0));
    32. while (!que.empty())
    33. {
    34. P current = que.top();
    35. que.pop();
    36. if (used[current.second] || current.first > d[current.second])
    37. {
    38. continue;
    39. }
    40. used[current.second] = true;
    41. for (int i = 0; i < edges[current.second].size(); i++)
    42. {
    43. P toEdge = edges[current.second][i];
    44. int relativeEdge = toEdge.first > mid ? 1 : 0;
    45. if (d[current.second] + relativeEdge < d[toEdge.second])
    46. {
    47. d[toEdge.second] = d[current.second] + relativeEdge;
    48. que.push(P(d[toEdge.second], toEdge.second));
    49. }
    50. }
    51. }
    52. return d[n - 1] <= k;
    53. }
    54. void binarySearch()
    55. {
    56. int left = -1, right = maxt + 1;
    57. while (left + 1 < right)
    58. {
    59. int mid = (left + right) / 2;
    60. if (judgeByDijkstra(mid))
    61. {
    62. right = mid;
    63. }
    64. else
    65. {
    66. left = mid;
    67. }
    68. }
    69. printf("%d\n", right);
    70. }
    71. bool judgeIfCanGet()
    72. {
    73. for (int i = 0; i < n; i++)
    74. {
    75. d[i] = inf;
    76. used[i] = false;
    77. }
    78. d[0] = 0;
    79. priority_queue, greater

      > que;

    80. que.push(P(d[0], 0));
    81. while (!que.empty())
    82. {
    83. P current = que.top();
    84. que.pop();
    85. if (used[current.second] || current.first > d[current.second])
    86. {
    87. continue;
    88. }
    89. used[current.second] = true;
    90. for (int i = 0; i < edges[current.second].size(); i++)
    91. {
    92. P toEdge = edges[current.second][i];
    93. if (d[current.second] + toEdge.first < d[toEdge.second])
    94. {
    95. d[toEdge.second] = d[current.second] + toEdge.first;
    96. que.push(P(d[toEdge.second], toEdge.second));
    97. }
    98. }
    99. }
    100. return d[n - 1] != inf;
    101. }
    102. int main()
    103. {
    104. input();
    105. if (!judgeIfCanGet())
    106. {
    107. printf("-1\n");
    108. }
    109. else
    110. {
    111. binarySearch();
    112. }
    113. return 0;
    114. }

  • 相关阅读:
    他潜伏三年想插它后门,最终还是输给了另一个他
    【测试开发】用例篇 · 熟悉黑盒测试用例设计方法(1)等价类划分法、边界值法、判定表法
    玩玩群晖NAS-搭建一个私有的Git服务
    Java类加载机制
    Sui基金会与沙迦美国大学宣布合作开设区块链学院
    for update防止修改丢失但不起作用的解决办法
    操作系统的奋斗(一)
    前端之一阶段[HTML、CSS]问题记录
    教育案例分享 | 安全狗云安全体系为高校提升立体化纵深防御能力
    组合继承
  • 原文地址:https://blog.csdn.net/qq_53038151/article/details/132678911