有代价的单源最短路径

问题:有代价的单源最短路径,并要求存储路径。(求最短的路径,并使代价最小)

特点:

* 存储路径:决定了难以用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;
}







你可能感兴趣的:(ACM,pat,1018,单源有代价最短路)