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 }

 

posted @ 2020-03-09 12:19  tangq123  阅读(208)  评论(0)    收藏  举报