• 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. }

  • 相关阅读:
    TCP IP网络编程(六) 基于UDP的服务器端、客户端
    c++征途 --- 项目 --- 职工管理系统
    Gym 104025 M -Counting in Tree
    读《高性能MySQL》笔记---MySQL架构
    Spring中Bean的作用域和生命周期
    离子液体负载修饰磁性纳米材料四氧化三铁(Fe3O4)(齐岳bio)
    ExcelPatternTool 开箱即用的Excel工具包现已发布!
    C++入门必备基础知识(上篇)
    红黑树详解+模拟实现
    vue账号密码缓存本地不为空赋值到输入框盘点
  • 原文地址:https://blog.csdn.net/qq_53038151/article/details/132678911