1018. Public Bike Management (30)---dijk+dfs

思路:先用dijk求出最短路,利用pre[v]保存成另一个图,再用dfs深搜这个新图

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>

using namespace std;

const int inf=2100000000;
int Cmax,N,ed,M;
int w[1005]={0};
int g[1005][1005];
int dis[1005];
int book[1005]={0};//记录dis的记录情况
vector<int> pre[1005];
void init()
{
    for(int i=0;i<1005;i++)
        for(int j=0;j<1005;j++)
        {
            g[i][j]=inf;
            g[j][i]=inf;
        }

    for(int i=0;i<1005;i++)
    {
        dis[i]=inf;
    }
}

void dijk()
{
    for(int i=0;i<=N;i++)
    {
        if(g[0][i]!=inf)
        {
            dis[i]=g[0][i];
            pre[i].push_back(0);
        }
    }
    dis[0]=0;
    book[0]=1;
    for(int i=0;i<N;i++)
    {
        int u=-1;
        int minn=inf;
        for(int i=0;i<=N;i++)
        {
            if(book[i]==0&&dis[i]<minn)//找到dis没有记录过的最小点
            {
                minn=dis[i];
                u=i;
            }
        }

        if(u==-1)//剩下的点都不连通
            return;

        book[u]=1;

        for(int v=0;v<=N;v++)
        {
            if(book[v]==0&&g[u][v]!=inf)
            {
                if(dis[u]+g[u][v]<dis[v])
                {
                    dis[v]=dis[u]+g[u][v];
                    pre[v].clear();
                    pre[v].push_back(u);
                }
                else if(dis[u]+g[u][v]==dis[v])
                {
                    pre[v].push_back(u);
                }
            }
        }
    }
}

vector<int> ans,v;
int minneed=inf;
int minstore=inf;
void dfs(int id)
{
    if(id==0)
    {
        v.push_back(id);
        int need=0;
        int store=0;
        for(int i=v.size()-1;i>=0;i--)
        {
            if(w[v[i]]>0)
            {
                store+=w[v[i]];
            }
            else if(w[v[i]]<0)
            {
                if(store<=abs(w[v[i]]))
                {
                    need+=abs(w[v[i]])-store;
                    store=0;
                }
                else
                {
                    store-=abs(w[v[i]]);
                }
            }
        }
        if(need<minneed)
        {
            minneed=need;
            minstore=store;
            ans=v;
        }
        else if(need==minneed&&store<minstore)
        {
            minneed=need;
            minstore=store;
            ans=v;
        }

        v.pop_back();
        return;
    }


    v.push_back(id);
    for(int i=0;i<pre[id].size();i++)
    {
        dfs(pre[id][i]);
    }
    v.pop_back();

}

int main()
{
//    freopen("in.txt","r",stdin);

    scanf("%d %d %d %d",&Cmax,&N,&ed,&M);
    init();
    for(int i=1;i<=N;i++)
    {
        int t;
        scanf("%d",&t);
        w[i]=t-Cmax/2;
    }

    for(int i=0;i<M;i++)
    {
        int t1,t2,t;
        scanf("%d %d %d",&t1,&t2,&t);
        g[t1][t2]=t;
        g[t2][t1]=t;
    }

    dijk();
    dfs(ed);

    printf("%d ",minneed);
    for(int i=ans.size()-1;i>=0;i--)
    {
        printf("%d",ans[i]);
        if(i!=0)
            printf("->");
    }
    printf(" %d",minstore);


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值