1018 Public Bike Management (30 分)思路+测试样例 dij+DFS

题目链接

这是一个坑特别多而且值得深思的题

最短路嘛,一看就是dij,这里用一个数组存一下每一次的pre
pre定义是vector<int> pre[520]
这个题一个很需要注意的地方就是,它一共是N+1个点啊!!!!!

void dij(){
    d[0]=0;
    for (int i = 0; i <= N; ++i) {
        int u=-1,MIN=INF;
        for (int j = 0; j <= N ; ++j) {
            if(vis[j]==0 && d[j]<MIN){
                u=j;
                MIN=d[j];
            }
        }
        if(u==-1) return ;
        vis[u]=1;
        //cout<<"u1:"<<u<<endl;
        for (int j = 0; j <= N ; ++j) {
            if(vis[j]==0 && G[u][j]!=INF){
                if(d[j]>d[u]+G[u][j]){
                    d[j]=d[u]+G[u][j];
                    pre[j].clear();
                    pre[j].push_back(u);
                    //cout<<"u2:"<<u<<endl;
                }
                else if(d[j]==d[u]+G[u][j]){
                    pre[j].push_back(u);
                    //cout<<"u3:"<<u<<endl;
                }
            }

        }

    }
}

然后对你的pre数组进行DFS
到叶节点(即v=0)就计算一波need 和 remain
这个题不可以一边跑一边算的(可能受一些题的影响会这么干)因为它后面的remain是不可以用在前面的节点,所以只能从前面跑一波。
然后正常记录你所需要的
这个题其实相当于三个标尺。在need一样的时候比较remain也很重要。


void DFS(int v){
    if(v==0){//叶子节点
        //这个地方的操作要注意,必须是从0开始跑一遍
        //因为它必须要从头跑一遍啊
        int need=0,remain=0;
        int si=temp.size();
        for (int i = si-1; i >= 0 ; --i) {
            int id=temp[i];
            //cout<<"id"<<id<<endl;
            if(weight[id]>0){
                remain+=weight[id];
            }
            else{
                if(remain>abs(weight[id])){
                    remain-=abs(weight[id]);
                }
                else{
                    need+=abs(weight[id])-remain;
                    remain=0;
                }
            }

        }
        if(need<minNeed){
            minNeed=need;
            minRemain=remain;
            ans=temp;
        }
        else if(need==minNeed && remain<minRemain){
            minRemain=remain;
            ans=temp;
        }
        //temp.pop_back();
        return ;
    }

    if(!pre[v].empty()) {
        int len=pre[v].size();
        for (int i = 0; i < len ; ++i) {
            temp.push_back(pre[v][i]);
           // cout<<"pre"<<pre[v][i]<<endl;
            DFS(pre[v][i]);
            temp.pop_back();
        }
    }


}

然后涉及我自己的一些问题的话,就是说temp第一下没有把末尾那个点弄进去导致改了一小会,在DFS前先把sp搞数组里还是很有必要的

在这里插入图片描述
然后自己写的init函数,在N,M还没输入的时候就开始用了。。。
注意顺序啊喂!

感谢一下dl的样例:

10 2  2 2
2 10
0 1 1
1 2 1

3 0->1->2 5


10 3 3 3
11 0 10
0 1 1
1 2 1
2 3 1

0 0->1->2->3 6


10 4 4 5
6 7 5 0
0 1 1
0 2 1
1 3 1
2 3 1
3 4 1

3 0->2->3->4 0


10 4 4 4
6 0 11 0
0 1 1
1 2 1
2 3 1
3 4 1

4 0->1->2->3->4 1


10 4 4 8
0 11 3 0
0 1 2
0 2 3
0 3 2
1 2 1
2 3 1
1 4 2
2 4 1
3 4 2
0 0->2->4 1

10 6 6 8
8 9 4 6 7 2
0 1 1
0 2 1
1 3 1
2 3 1
3 4 1
3 5 2
4 6 1
5 6 1
0 0->1->3->4->6 0

写给自己:瓶颈期会过去,继续加油哇!

喔忘记贴代码咯:

#include<vector>
#include<iostream>
#include <algorithm>
#include <cmath>
#include<map>
#include <queue>
#include <stack>
#include<string.h>
using namespace std;
const int INF=100000;
int Cmax,N,sp,M;
int minNeed=INF,minRemain=INF;
int G[503][503];
int weight[503];
int vis[503]={0};
int d[503];
int w[503]={0};
vector<int> pre[502];
void init(){
    for (int i = 0; i <= N ; ++i) {
        for (int j = 0; j <= N ; ++j) {
            if(i!=j){
                G[i][j]=INF;
            }
        }

    }

    for (int i = 0; i <= N; ++i) {
        d[i]=INF;
    }
}
void dij(){
    d[0]=0;
    for (int i = 0; i <= N; ++i) {
        int u=-1,MIN=INF;
        for (int j = 0; j <= N ; ++j) {
            if(vis[j]==0 && d[j]<MIN){
                u=j;
                MIN=d[j];
            }
        }
        if(u==-1) return ;
        vis[u]=1;
        //cout<<"u1:"<<u<<endl;
        for (int j = 0; j <= N ; ++j) {
            if(vis[j]==0 && G[u][j]!=INF){
                if(d[j]>d[u]+G[u][j]){
                    d[j]=d[u]+G[u][j];
                    pre[j].clear();
                    pre[j].push_back(u);
                    //cout<<"u2:"<<u<<endl;
                }
                else if(d[j]==d[u]+G[u][j]){
                    pre[j].push_back(u);
                    //cout<<"u3:"<<u<<endl;
                }
            }

        }

    }
}
vector<int> temp;
vector<int> ans;

void DFS(int v){
    if(v==0){//叶子节点
        //这个地方的操作要注意,必须是从0开始跑一遍
        //因为它必须要从头跑一遍啊
        int need=0,remain=0;
        int si=temp.size();
        for (int i = si-1; i >= 0 ; --i) {
            int id=temp[i];
            //cout<<"id"<<id<<endl;
            if(weight[id]>0){
                remain+=weight[id];
            }
            else{
                if(remain>abs(weight[id])){
                    remain-=abs(weight[id]);
                }
                else{
                    need+=abs(weight[id])-remain;
                    remain=0;
                }
            }

        }
        if(need<minNeed){
            minNeed=need;
            minRemain=remain;
            ans=temp;
        }
        else if(need==minNeed && remain<minRemain){
            minRemain=remain;
            ans=temp;
        }
        //temp.pop_back();
        return ;
    }

    if(!pre[v].empty()) {
        int len=pre[v].size();
        for (int i = 0; i < len ; ++i) {
            temp.push_back(pre[v][i]);
           // cout<<"pre"<<pre[v][i]<<endl;
            DFS(pre[v][i]);
            temp.pop_back();
        }
    }


}
int main(){



    cin>>Cmax>>N>>sp>>M;
    init();
    for (int i = 1; i <= N; ++i) {
        cin>>weight[i];
        weight[i]-=Cmax/2;

    }
    for (int i = 0; i < M; ++i) {
        int u,v, l;
        cin>>u>>v>>l;
        G[u][v]=l;
        G[v][u]=l;
       // cout<<"G[v][u]:"<<G[u][v]<<endl;
    }
    dij();
    //cout<<G[0][2]<<G[1][2]<<endl;
    temp.push_back(sp);
    DFS(sp);

    cout<<minNeed<<" ";
    int len=ans.size();
    for (int i = len-1; i >= 0 ; --i) {
        cout<<ans[i];
        if(i!=0){
            cout<<"->";
        }

    }
    cout<<" "<<minRemain<<endl;

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用堆优化的 Dijkstra 算法来求解最短路径的示例代码,其中使用了 vector 来表示图的邻接表: ```cpp #include <iostream> #include <vector> #include <queue> #include <limits> using namespace std; typedef pair<int, int> pii; const int INF = numeric_limits<int>::max(); vector<int> dijkstra(const vector<vector<pii>>& graph, int source) { int n = graph.size(); vector<int> dist(n, INF); dist[source] = 0; priority_queue<pii, vector<pii>, greater<pii>> pq; pq.push({0, source}); while (!pq.empty()) { int u = pq.top().second; int d = pq.top().first; pq.pop(); if (d > dist[u]) { continue; // 已经找到了更短的路径 } for (const auto& edge : graph[u]) { int v = edge.first; int w = edge.second; if (dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.push({dist[v], v}); } } } return dist; } int main() { int n = 5; // 图的顶点数 int m = 7; // 图的边数 vector<vector<pii>> graph(n); // 构建图的邻接表 graph[0].push_back({1, 2}); graph[0].push_back({2, 4}); graph[1].push_back({2, 1}); graph[1].push_back({3, 7}); graph[2].push_back({3, 3}); graph[2].push_back({4, 5}); graph[3].push_back({4, 2}); graph[4].push_back({3, 1}); int source = 0; vector<int> dist = dijkstra(graph, source); cout << "Shortest distances from node " << source << ":" << endl; for (int i = 0; i < n; ++i) { cout << "Node " << i << ": " << dist[i] << endl; } return 0; } ``` 上述代码中,我们使用堆优化的 Dijkstra 算法来找到从源节点到其他节点的最短距离。图的邻接关系使用 vector<vector<pii>> 来表示,其中 pii 表示边的目标节点和权重。你可以根据需要修改图的顶点数、边数和邻接表来适应不同的场景。输出结果将会显示源节点到其他节点的最短距离。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值