问题:有代价的单源最短路径,并要求存储路径。(求最短的路径,并使代价最小)
特点:
* 存储路径:决定了难以用dijkstra,可以用flody,用path[i][j]表示 i 想走到 j 迈出的第一步。假设k是 i->j 的中间节点,更新时候用path[i][j] = path[i][k],具体做法见link。但是flody比较耗时(O(N^3))
* 有代价:如果想用flody的话,有要求代价最小,就需要将最短路相等的都记录下来。边一多代价更上去了。所以还是dfs比较方便。
例题:
PAT 1018(http://pat.zju.edu.cn/contests/pat-a-practise/1018)
这道题关键要想到用dfs,就好做了。Code:
#include<iostream>
#include<memory.h>
#include<vector>
using namespace std;
#define N 505
int map[N][N];
vector<int> path,min_path;
int bike[N];
bool visit[N];
#define INF 10000000
int dest,n,req;//req:require
int min_d,min_bring,min_back;
int cur_d,cur_bring,cur_back;
void dfs(int p)
{
int i;
if(p==dest)
{
if(cur_d<min_d ||
cur_d==min_d && cur_bring < min_bring||
cur_d == min_d && cur_bring == min_bring && cur_back<min_back)
{
min_d = cur_d;
min_bring = cur_bring;
min_back = cur_back;
min_path = path;
}
return;
}
else
{
for(i=0;i<=n;i++)
{
if(!visit[i]&&map[p][i]!=INF)
{
cur_d += map[p][i];
visit[i] = true;
path.push_back(i);
if(bike[i]<req)
{
if(cur_back >= req-bike[i])
{
cur_back -= (req-bike[i]);
dfs(i);
cur_back += (req-bike[i]);
}
else
{
int t = cur_back;
cur_bring += req-bike[i] - cur_back;
cur_back = 0;
dfs(i);
cur_back = t;
cur_bring -= req-bike[i] - cur_back;
}
}
else
{
cur_back += bike[i]-req;
dfs(i);
cur_back -= (bike[i]-req);
}
path.pop_back();
visit[i] = false;
cur_d-=map[p][i];
}
}
}
}
int main()
{
int cm,m,i,j,t,a,b;
scanf("%d%d%d%d",&cm,&n,&dest,&m);
req = cm/2;
for(i=0;i<n;i++)
scanf("%d",&bike[i+1]);
memset(visit,false,sizeof(visit));
visit[0] = true;
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
map[i][j] = INF;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&t);
if(map[a][b]>t)
map[a][b] = map[b][a] = t;
}
min_d = min_bring = min_back = INF;
cur_d = cur_bring = cur_back = 0;
path.push_back(0);
dfs(0);
cout<<min_bring<<" ";
printf("%d",min_path[0]);
for(i=1;i<min_path.size();i++)
printf("->%d",min_path[i]);
cout<<" "<<min_back<<endl;
return 0;
}