• 176. 装满的油箱 图 - 拆点


     题目:176. 装满的油箱 - AcWing题库

    有 N 个城市(编号 0、1…N−1)和 M 条道路,构成一张无向图

    在每个城市里边都有一个加油站,不同的加油站的单位油价不一样。

    现在你需要回答不超过 100 个问题,在每个问题中,请计算出一架油箱容量为 C 的车子,从起点城市 S 开到终点城市 E 至少要花多少油钱?

    注意: 假定车子初始时油箱是空的。

    输入格式

    第一行包含两个整数 N 和 M。

    第二行包含 N 个整数,代表 N 个城市的单位油价,第 i 个数即为第 i 个城市的油价 pi。

    接下来 M 行,每行包括三个整数 u,v,d,表示城市 u 与城市 v 之间存在道路,且车子从 u 到 v 需要消耗的油量为 d。

    接下来一行包含一个整数 q,代表问题数量。

    接下来 q 行,每行包含三个整数 C、S、E,分别表示车子油箱容量 C、起点城市 S、终点城市 E。

    输出格式

    对于每个问题,输出一个整数,表示所需的最少油钱。

    如果无法从起点城市开到终点城市,则输出 impossible

    每个结果占一行。

    数据范围

    1≤N≤1000,
    1≤M≤10000,
    1≤pi≤100,
    1≤d≤100,
    1≤C≤100,
    1≤q≤100。

    输入样例:

    1. 5 5
    2. 10 10 20 12 13
    3. 0 1 9
    4. 0 2 8
    5. 1 2 1
    6. 1 3 11
    7. 2 3 7
    8. 2
    9. 10 0 3
    10. 20 1 4

    输出样例:

    1. 170
    2. impossible
    1. #include
    2. #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    3. #define endl '\n'
    4. using namespace std;
    5. typedef pair<int, int> PII;
    6. typedef long long ll;
    7. const int N = 1010, M = 20010, C = 110;
    8. struct Ver
    9. {
    10. int d, u, c;//距离,点,油量
    11. bool operator< (const Ver &W)const
    12. {
    13. return d > W.d;
    14. }
    15. };
    16. int c, S, T;
    17. int h[N], e[M], w[M], ne[M], idx;
    18. int dist[N][C];
    19. int price[N];
    20. bool st[N][C];
    21. int n, m;
    22. void add(int a, int b, int c)
    23. {
    24. e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
    25. }
    26. int dijkstra()
    27. {
    28. memset(st, false, sizeof st);
    29. memset(dist, 0x3f, sizeof dist);
    30. dist[S][0] = 0;
    31. priority_queue q;
    32. q.push({0, S, 0});
    33. while(q.size())
    34. {
    35. auto t = q.top();
    36. q.pop();
    37. if(t.u == T)return t.d;
    38. if(st[t.u][t.c])continue;
    39. st[t.u][t.c] = true;
    40. if(t.c < c)
    41. {
    42. if(dist[t.u][t.c + 1] > dist[t.u][t.c] + price[t.u])
    43. {
    44. dist[t.u][t.c + 1] = dist[t.u][t.c] + price[t.u];
    45. q.push({dist[t.u][t.c + 1], t.u, t.c + 1});
    46. }
    47. }
    48. for(int i = h[t.u]; i != -1; i = ne[i])
    49. {
    50. int j = e[i];
    51. if(t.c >= w[i])
    52. {
    53. if(dist[j][t.c - w[i]] >= dist[t.u][t.c])
    54. {
    55. dist[j][t.c - w[i]] = dist[t.u][t.c];
    56. q.push({dist[j][t.c - w[i]], j, t.c - w[i]});
    57. }
    58. }
    59. }
    60. }
    61. return -1;
    62. }
    63. int main()
    64. {
    65. IOS
    66. cin >> n >> m;
    67. for(int i = 0; i < n; i ++)cin >> price[i];
    68. memset(h, -1, sizeof h);
    69. while(m --)
    70. {
    71. int a, b, c;
    72. cin >> a >> b >> c;
    73. add(a, b, c), add(b, a, c);
    74. }
    75. int Q;
    76. cin >> Q;
    77. while(Q --)
    78. {
    79. cin >> c >> S >> T;
    80. int t = dijkstra();
    81. if(t == -1)cout << "impossible" << endl;
    82. else cout << t << endl;
    83. }
    84. return 0;
    85. }

     题目难点在于如何建图,有一点点类似分层图,但也不是分层图

    拆点:把一个点拆成C个点,用二维数组表示,只有n不大的时候可以这样做

    因为C上限为100,所以1000个点就拆成了100000个点,边数为20000

    每个点拆成的若干个点之间也要连C - 1条边,共计100000条边

    复杂度为100 * 120000 * log(100000),是可以接受的。

  • 相关阅读:
    从零实现Web框架Geo教程-中间件-05
    iOS——类与对象底层探索
    Spring In Action 5 学习笔记 chapter8 RabbitMQ(AMQP)要点
    消息队列系列5 - RabbitMQ安装与测试 (荣耀典藏版)
    python常用pandas函数nlargest 和 nsmallest及其手动实现
    c++新标准有用的语法特性
    0基础学习 Android 开发用 Kotlin 编程语言
    C语言学习之路(基础篇)—— 指针(上)
    awk命令实例
    『现学现忘』Docker基础 — 37、ONBUILD指令介绍
  • 原文地址:https://blog.csdn.net/a1695574118/article/details/132741219