标签:不能 使用 n+1 int turn ack stream info 最短路径
题目较难,不能使用 Dijkstra内嵌第二标尺的方法来做这道题,所以改用Dijkstra + DFS。
Dijkstra 部分直接写模版,来获取从起点S到其它各顶点的最短路径。
DFS 部分来遍历所有路径,路径上 判断某顶点 要补给资源,还是要拿走资源,与前一个顶点的判断结果有关。(如果对于这题DFS的作用没搞清楚,而继续以前的套路,那么测试点5、7无法通过)
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 510; 6 const int inf = 0x3fffffff; 7 //图的要素 8 int G[maxn][maxn]; 9 int visited[maxn] = {false}; 10 //dijkstra算法的yaosu 11 int d[maxn]; 12 vector<int> pre[maxn]; 13 vector<int> path,tempPath; 14 15 //第二标尺的要素 16 int weight[maxn]; 17 int minRemain = inf,minNeed = inf; 18 19 int C,N,S,M; 20 21 void Dijkstra(int s) { 22 //第一步,初始化d[] 23 fill(d,d+maxn,inf); 24 d[s] = 0; 25 //第二步,循环 N+1次 26 for(int i = 0; i < N; ++i) { 27 //第三步,遍历所有顶点 u,找到最小d[u] ,并标记为已访问 28 int u = -1, MIN = inf; 29 for(int j = 0; j < N+1; ++j) { 30 if(visited[j] == false && d[j] < MIN) { 31 u = j; 32 MIN = d[j]; 33 } 34 } 35 if(u == -1) return ; 36 visited[u] = true; 37 //第四步,遍历所有顶点 v,用顶点 u更新 d[v] 38 for(int v = 0; v < N+1; ++v) { 39 if(visited[v] == false && G[u][v] != inf) { 40 if(d[u] + G[u][v] < d[v]) { 41 d[v] = d[u] + G[u][v]; 42 pre[v].clear(); 43 pre[v].push_back(u);// u是 v的前驱结点 44 } else if(d[u] + G[u][v] == d[v]) 45 pre[v].push_back(u);// u是 v的前驱结点之一 46 } 47 } 48 } 49 } 50 51 void DFS(int v) { 52 if(v == 0) { 53 tempPath.push_back(v); 54 int need = 0, remain = 0; 55 for(int i = tempPath.size()-1; i >= 0 ; --i) { 56 int id = tempPath[i]; 57 if(weight[id] > 0) //点权大于0,说明要拿走一部分车辆 58 remain += weight[id]; 59 else { 60 if(remain > abs(weight[id]))//如果手头的车辆足够补给 61 remain -= abs(weight[id]); 62 else { 63 need += abs(weight[id]) - remain;//不够的部分从PBMC携带 64 remain = 0; 65 } 66 } 67 } 68 if(need < minNeed) { 69 minNeed = need; 70 minRemain = remain; 71 path = tempPath; 72 } else if(need == minNeed && remain < minRemain) { 73 minRemain = remain; 74 path = tempPath; 75 } 76 tempPath.pop_back(); 77 return; 78 } 79 tempPath.push_back(v); 80 for(int i = 0; i < pre[v].size(); ++i) 81 DFS(pre[v][i]); 82 tempPath.pop_back(); 83 } 84 85 int main() { 86 cin>>C>>N>>S>>M; 87 //初始化邻接矩阵 88 fill(G[0],G[0]+maxn*maxn,inf); 89 for(int i = 1; i <= N; ++i) {//顶点的点权 90 cin>>weight[i]; 91 weight[i] -= C/2; //点权减去容量的一半 92 } 93 int u,v; 94 for(int i = 0; i < M; ++i) {//两顶点间的边权 95 cin>>u>>v; 96 cin>>G[u][v]; 97 G[v][u] = G[u][v]; 98 } 99 Dijkstra(0); // 起点 0 100 DFS(S);//终点 S 101 printf("%d ",minNeed); 102 for(int i = path.size()-1; i>=0 ; --i) { 103 if( i < path.size()-1) printf("->"); 104 printf("%d",path[i]); 105 } 106 printf(" %d",minRemain); 107 return 0; 108 }
1018 Public Bike Management(考察Dijkstra + DFS)
标签:不能 使用 n+1 int turn ack stream info 最短路径
原文地址:https://www.cnblogs.com/keep23456/p/12448015.html