题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024

还是Dijkstra+DFS,重点是Dijkstra里的循环范围(因为不含起始点所以要+1)以及DFS函数的写法

代码

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<vector>
  5. using namespace std;
  6. const int maxn = 510;
  7. const int inf = 0x3fffffff;
  8. int cmax, n, sp, m;
  9. int minNeed = inf, minRemain = inf;
  10. int weight[maxn], G[maxn][maxn], d[maxn];
  11. vector<int>pre[maxn];
  12. vector<int> path, tempPath;
  13. bool vis[maxn] = {false};
  14. void Dijkstra(int s){
  15. fill(d, d + maxn, inf);
  16. d[s] = 0;
  17. for(int i = 0; i <= n; i++){
  18. int u = -1, min = inf;
  19. for(int j = 0; j <= n; j++){
  20. if(vis[j] == false && d[j] < min){
  21. u = j;
  22. min = d[j];
  23. }
  24. }
  25. if(u == -1) return;
  26. vis[u] = true;
  27. for(int v = 0; v <= n; v++){
  28. if(vis[v] == false && G[u][v] != inf){
  29. if(G[u][v] + d[u] < d[v]){
  30. d[v] = G[u][v] + d[u];
  31. pre[v].clear();
  32. pre[v].push_back(u);
  33. } else if(G[u][v] + d[u] == d[v]){
  34. pre[v].push_back(u);
  35. }
  36. }
  37. }
  38. }
  39. }
  40. void DFS(int v){
  41. if(v == 0){//递归边界
  42. tempPath.push_back(v);
  43. int need = 0, remain = 0;
  44. for(int i = tempPath.size() - 1; i >= 0; i--){
  45. int id = tempPath[i];
  46. if(weight[id] > 0){//多了
  47. remain += weight[id];
  48. } else {//少了要补充
  49. if(remain > abs(weight[id])){//如果自己的够,那给光
  50. remain -= abs(weight[id]);
  51. } else {//如果不够,那就再need上面增加差的那一部分
  52. need += abs(weight[id]) - remain;
  53. remain = 0;//并把剩下的全给光
  54. }
  55. }
  56. }
  57. if(need < minNeed){
  58. minNeed = need;
  59. minRemain = remain;
  60. path = tempPath;
  61. } else if(need == minNeed && remain < minRemain){
  62. minRemain = remain;
  63. path = tempPath;
  64. }
  65. tempPath.pop_back();
  66. return;
  67. }
  68. tempPath.push_back(v);
  69. for(int i = 0; i < pre[v].size(); i++){
  70. DFS(pre[v][i]);
  71. }
  72. tempPath.pop_back();
  73. }
  74. int main(){
  75. scanf("%d%d%d%d", &cmax, &n, &sp, &m);
  76. fill(G[0], G[0] + maxn * maxn, inf);
  77. for(int i = 1; i <= n; i++){
  78. scanf("%d", &weight[i]);
  79. weight[i] -= cmax / 2;
  80. }
  81. int u, v;
  82. for(int i = 0 ;i < m; i++){
  83. scanf("%d%d", &u, &v);
  84. scanf("%d", &G[u][v]);
  85. G[v][u] = G[u][v];
  86. }
  87. Dijkstra(0);
  88. DFS(sp);
  89. printf("%d ", minNeed);
  90. for(int i = path.size() - 1; i >= 0; i--){
  91. printf("%d", path[i]);
  92. if(i != 0) printf("->");
  93. }
  94. printf(" %d", minRemain);
  95. return 0;
  96. }