题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024
还是Dijkstra+DFS,重点是Dijkstra里的循环范围(因为不含起始点所以要+1)以及DFS函数的写法
代码
#include<algorithm>#include<iostream>#include<cstdio>#include<vector>using namespace std;const int maxn = 510;const int inf = 0x3fffffff;int cmax, n, sp, m;int minNeed = inf, minRemain = inf;int weight[maxn], G[maxn][maxn], d[maxn];vector<int>pre[maxn];vector<int> path, tempPath;bool vis[maxn] = {false};void Dijkstra(int s){fill(d, d + maxn, inf);d[s] = 0;for(int i = 0; i <= n; i++){int u = -1, min = inf;for(int j = 0; j <= n; j++){if(vis[j] == false && d[j] < min){u = j;min = d[j];}}if(u == -1) return;vis[u] = true;for(int v = 0; v <= n; v++){if(vis[v] == false && G[u][v] != inf){if(G[u][v] + d[u] < d[v]){d[v] = G[u][v] + d[u];pre[v].clear();pre[v].push_back(u);} else if(G[u][v] + d[u] == d[v]){pre[v].push_back(u);}}}}}void DFS(int v){if(v == 0){//递归边界tempPath.push_back(v);int need = 0, remain = 0;for(int i = tempPath.size() - 1; i >= 0; i--){int id = tempPath[i];if(weight[id] > 0){//多了remain += weight[id];} else {//少了要补充if(remain > abs(weight[id])){//如果自己的够,那给光remain -= abs(weight[id]);} else {//如果不够,那就再need上面增加差的那一部分need += abs(weight[id]) - remain;remain = 0;//并把剩下的全给光}}}if(need < minNeed){minNeed = need;minRemain = remain;path = tempPath;} else if(need == minNeed && remain < minRemain){minRemain = remain;path = tempPath;}tempPath.pop_back();return;}tempPath.push_back(v);for(int i = 0; i < pre[v].size(); i++){DFS(pre[v][i]);}tempPath.pop_back();}int main(){scanf("%d%d%d%d", &cmax, &n, &sp, &m);fill(G[0], G[0] + maxn * maxn, inf);for(int i = 1; i <= n; i++){scanf("%d", &weight[i]);weight[i] -= cmax / 2;}int u, v;for(int i = 0 ;i < m; i++){scanf("%d%d", &u, &v);scanf("%d", &G[u][v]);G[v][u] = G[u][v];}Dijkstra(0);DFS(sp);printf("%d ", minNeed);for(int i = path.size() - 1; i >= 0; i--){printf("%d", path[i]);if(i != 0) printf("->");}printf(" %d", minRemain);return 0;}
