1018 Public Bike Management(考察Dijkstra + DFS)
题目较难,不能使用 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(visited,visited+maxn,false); 24 fill(d,d+maxn,inf); 25 d[s] = 0; 26 //第二步,循环 N+1次 27 for(int i = 0; i < N; ++i) { 28 //第三步,遍历所有顶点 u,找到最小d[u] ,并标记为已访问 29 int u = -1, MIN = inf; 30 for(int j = 0; j < N+1; ++j) { 31 if(visited[j] == false && d[j] < MIN) { 32 u = j; 33 MIN = d[j]; 34 } 35 } 36 if(u == -1) return ; 37 visited[u] = true; 38 //第四步,遍历所有顶点 v,用顶点 u更新 d[v] 39 for(int v = 0; v < N+1; ++v) { 40 if(visited[v] == false && G[u][v] != inf) { 41 if(d[u] + G[u][v] < d[v]) { 42 d[v] = d[u] + G[u][v]; 43 pre[v].clear(); 44 pre[v].push_back(u);// u是 v的前驱结点 45 } else if(d[u] + G[u][v] == d[v]) 46 pre[v].push_back(u);// u是 v的前驱结点之一 47 } 48 } 49 } 50 } 51 52 void DFS(int v) { 53 if(v == 0) { 54 tempPath.push_back(v); 55 int need = 0, remain = 0; 56 for(int i = tempPath.size()-1; i >= 0 ; --i) { 57 int id = tempPath[i]; 58 if(weight[id] > 0) //点权大于0,说明要拿走一部分车辆 59 remain += weight[id]; 60 else { 61 if(remain > abs(weight[id]))//如果手头的车辆足够补给 62 remain -= abs(weight[id]); 63 else { 64 need += abs(weight[id]) - remain;//不够的部分从PBMC携带 65 remain = 0; 66 } 67 } 68 } 69 if(need < minNeed) { 70 minNeed = need; 71 minRemain = remain; 72 path = tempPath; 73 } else if(need == minNeed && remain < minRemain) { 74 minRemain = remain; 75 path = tempPath; 76 } 77 tempPath.pop_back(); 78 return; 79 } 80 tempPath.push_back(v); 81 for(int i = 0; i < pre[v].size(); ++i) 82 DFS(pre[v][i]); 83 tempPath.pop_back(); 84 } 85 86 int main() { 87 cin>>C>>N>>S>>M; 88 //初始化邻接矩阵 89 fill(G[0],G[0]+maxn*maxn,inf); 90 for(int i = 1; i <= N; ++i) {//顶点的点权 91 cin>>weight[i]; 92 weight[i] -= C/2; //点权减去容量的一半 93 } 94 int u,v; 95 for(int i = 0; i < M; ++i) {//两顶点间的边权 96 cin>>u>>v; 97 cin>>G[u][v]; 98 G[v][u] = G[u][v]; 99 } 100 Dijkstra(0); // 起点 0 101 DFS(S);//终点 S 102 printf("%d ",minNeed); 103 for(int i = path.size()-1; i>=0 ; --i) { 104 if( i < path.size()-1) printf("->"); 105 printf("%d",path[i]); 106 } 107 printf(" %d",minRemain); 108 return 0; 109 }


浙公网安备 33010602011771号