[PATクラスA単一ソース最短パスC ++] 1018パブリックバイク管理(30ポイント)

この種のポイントウェイトまたはエッジウェイトは単純な加算の問題ではありません。一般的に、DFSを使用して計算する必要があります。

ダイクストラ+ DFS

# include <iostream>
# include <vector>
# include <algorithm>

using namespace std;

/* 求最短路径,第二标尺是从起点带最少的单车 */ 

const int MAXV = 510;
const int INF  = 0xffffff; 

struct Node{
    
    
    int v, dis;
};

vector<int> V(510);  // 点权
vector<Node> G[510]; // 边权
int dist[510];
int vis[510];
vector<int> pre[510];

int Cmax, N, ed, M;
int st = 0; // 起点是索引0; 


void Dijkstra(int s){
    
    
    fill(dist, end(dist), INF);
    fill(vis, end(vis), false);
    dist[s] = 0;
    
    for(int i = 0;i < N;++i){
    
    
        int u = -1;
        int MIN = INF;
        for(int j = 0; j < N ;++j){
    
    
            if(vis[j] == false && dist[j] < MIN){
    
    
                u = j;
                MIN = dist[j];
            }
        }
        if(u == -1) return;
        vis[u] = true;
        for(Node next: G[u]){
    
    
            int v = next.v ,uvDis = next.dis;
            if(vis[v] == false){
    
    
                if(dist[u] + uvDis  < dist[v]){
    
    
                    dist[v] = dist[u] + uvDis;
                    pre[v].clear();
                    pre[v].push_back(u);
                }
                else
                if(dist[u] + uvDis == dist[v]){
    
    
                    pre[v].push_back(u);
                }
            }
            
        }
    }
}

int minNeed = INF, minRemain = INF; // 从PBMC出发带走的单车数量,从终点带回PBMC的单车数量
vector<int> path, tempPath;

void DFS(int v){
    
    
    if(v == st){
    
    
        tempPath.push_back(st);

        int need = 0, remain = 0;
        for(int i = tempPath.size() - 1;i >= 0;--i){
    
    
            int id = tempPath[i];
            if(V[id] > 0){
    
     // 当前站点补给多了,不需要补给,需要带走补给,所以remain的多了 ,need不变
                remain += V[id]; // 补给数量remain变多了
                // need = need; // 不需要补给,所以need不变
            } 
            else{
    
     // 当前站点需要补给,所以remain少了,need多了
                if( remain < (-V[id]) ){
    
     // 带来的不够补给
                    need += (-V[id]) - remain; // 所以need还需要(-V[id]) - remain数量的更多补给
                    remain = 0; // 把能补给的都补给完了
                } else {
    
     // 带来的够补给
                    remain -= (-V[id]); // 所以需要补给(-V[id])数量
                    // need = need; // 够补给,所以need不变
                }
            }
        }
        if(need < minNeed){
    
    
            minNeed = need;
            minRemain = remain;
            path = tempPath;
        } 
        else
        if(need == minNeed && remain < minRemain){
    
    
            minRemain = remain;
            path = tempPath;
        }
        tempPath.pop_back();
    }

    tempPath.push_back(v);
    for(int u: pre[v]){
    
    
        DFS(u);
    }
    tempPath.pop_back();
}

int main(){
    
    
    cin >> Cmax >> N >> ed >> M;
    for(int i = 1;i <= N;++i){
    
    
        cin >> V[i];
        V[i] -= Cmax/2;
    }V[0] = 0;
    for(int i = 0;i < M;++i){
    
    
        int u, v, len;
        cin >> u >> v >> len;
        G[u].push_back({
    
    v, len});
        G[v].push_back({
    
    u, len});
    }
    Dijkstra(st);
    DFS(ed);
    
    cout << minNeed << " ";
    for(int i = path.size() - 1;i >= 0;--i){
    
    
        cout << path[i];
        if(i != 0) 
            cout << "->";
        else
            cout << " ";
    }
    cout << minRemain << endl;

    
    return 0;
}

おすすめ

転載: blog.csdn.net/MYMarcoreus/article/details/113815408