1018. Public Bike Management (30)

1018. Public Bike Management (30)
思路:用dijkstra算法求出并用path记录多条路径,然后dfs筛选最优路径
注意:send和back的记录;在沿途中,如果count<0的话,说明需要send,比如0->4,4,7,从原点出发,经过4,为使其perfect,需要从原点发送bike,最终结果为,send=2,back=2(并不是send和back中一定有一个为0)

#include <stdio.h>
#include <stdlib.h>
#define MAX 500+1
#define INF 999999999
struct path
{
    int size;
    int vp[MAX];//vertex_pervious v;
}path[MAX];//储存满足条件的多条最短路径
int stack[MAX],top=0;//储存路径
int anspath[MAX],x=0;//储存最终结果路径
int a[MAX][MAX],vertex[MAX];//邻接矩阵和顶点信息
int dist[MAX],visited[MAX];//dist数组和visited数组
int cmax,n,sp,m;//四个参量
int send=INF,back=INF;//send和back数量
void Initpath(void)
{
    int i,j;
    for(i=0;i<=n;++i)
        for(j=0;j<=n;++j)
            path[i].vp[j]=-1;
}
void DFS(int v)//找到最优路径
{
    int i;
    stack[top++]=v;//每次将顶点v收入stack保存路径
    if(v==0)//标志该次路径结束,比较选择最短路径
    {
        int s=0,count=0;
        for(int i=top-2;i>=0;--i)  
        {
            count+=vertex[stack[i]]-cmax/2;
            if(count<0)//小于0,则更新s,并把count置为0;
            {
                s+=-count;
                count=0;
            }
        }  
        if(s<send||(s==send&&count<back))  
        {
            send=s;  
            back=count;
            x=0;
            for(i=top-1;i>=0;--i)
                anspath[x++]=stack[i];
        }
        return;
    }
    for(i=0;i<path[v].size;++i)//对v的所有前驱节点进行递归调用
    {
        DFS(path[v].vp[i]);
        --top;//pop栈顶元素
    }
}
int main()
{
    scanf("%d %d %d %d",&cmax,&n,&sp,&m);
    for(int v=1;v<=n;++v)//读入顶点信息
        scanf("%d",&vertex[v]);
    for(int i=0;i<=n;++i)
    {
        visited[i]=0;//初始化visited数组
        for(int j=0;j<=n;++j)//初始化邻接矩阵
        {
            if(i!=j)
                a[i][j]=INF;
            else
                a[i][j]=0;
        }
    }
    for(int i=0;i<m;++i)//读入边数据
    {
        int u,v,w;
        scanf("%d %d %d",&u,&v,&w);
        a[u][v]=a[v][u]=w;
    }
    Initpath();
    for(int i=0;i<=n;++i)//初始化dist数组和路径
    {
        dist[i]=a[0][i];
        if(i!=0&&a[0][i]<INF)
            path[i].vp[path[i].size++]=0;
    }
    visited[0]=1;
    int min,v,w;
    for(int i=1;i<=n;++i)//dijkstra找到多条路径
    {
        min=INF;
        for(int j=0;j<=n;++j)
        {
            if(visited[j]==0&&dist[j]<min)
            {
                min=dist[j];
                v=j;
            }
        }
        visited[v]=1;
        for(w=0;w<=n;++w)
        {
            if(visited[w]==0&&a[v][w]<INF)
            {
                if(dist[w]>dist[v]+a[v][w])
                {
                    dist[w]=dist[v]+a[v][w];
                    path[w].vp[0]=v;
                    path[w].size=1;
                }
                else if(dist[w]==dist[v]+a[v][w])
                    path[w].vp[path[w].size++]=v;
            }
        }
    }
    DFS(sp);//dfs找到最优路径
    printf("%d ",send);
    for(int i=0;i<x-1;++i)
        printf("%d->",anspath[i]);
    printf("%d %d",sp,back);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值