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);
}