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(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 }

猜你喜欢

转载自www.cnblogs.com/keep23456/p/12448015.html