最短路径问题-----单源Dijkstra算法()

题目:pat—1018、Public Bike Management


题目思路:

  

  先用Dijkstra算出多条最短路径,并用vector<int> pre[n+1]存路径,再用DFS的方法遍历一遍路径,进行筛选。


代码展示:

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=1e3+5;
int p,n,endx,m,inf=999999999;
int cur[maxn],d[maxn],e[maxn][maxn];
bool vis[maxn+1];
vector <int> pre[maxn+1];
int minback=inf,mintake=inf,ans[maxn],tmp[maxn];
void init() {                             //初始化
	cin>>p>>n>>endx>>m;
	p/=2;
	memset(vis,false,sizeof(vis));
	cur[0]=0;
	for (int i=1; i<=n; i++) {
		pre[i].push_back(0);
		cin>>cur[i];
	}
	for (int i=0; i<=n; i++)
		for (int j=0; j<=n; j++) {
			if (i==j) e[i][j]=0;
			else e[i][j]=inf;
		}
	for (int i=1; i<=m; i++) {
		int v1,v2,val;
		cin>>v1>>v2>>val;
		e[v1][v2]=val;
		e[v2][v1]=val;
	}

}
void Dijkstra() {           //最短路径
	vis[0]=true;
	for (int i=0; i<=n; i++) d[i]=e[0][i]; //初始化距离

	for (int i=1; i<=n; i++) {
		int u,mind=inf;
		for (int j=0; j<=n; j++) if (!vis[j] && d[j]<mind ) {
				mind=d[j];
				u=j;
			}
		vis[u]=true;
		for (int v=0; v<=n; v++) if (u!=v && e[u][v]<inf ) {
				if (d[v]>d[u]+e[u][v]) {
					d[v]=d[u]+e[u][v];
					pre[v].clear();
					pre[v].push_back(u);
				} else if ( d[v]==(d[u]+e[u][v]) ) {
					pre[v].push_back(u);
				}
			}
	}
}
void Dfs(int endx,int step){ //在已经求出的多条最短路径中筛选出最优的一条,分别以take(带过去的自行车数量)和back(带回来的数量)作为第一、第二标准
	tmp[step]=endx;
	if (endx==0) {
		int sum=0,take=0;
		for (int i=step-1;i>=1;i--){
			if (sum+cur[tmp[i]]<p) {
				take+=(p-sum-cur[tmp[i]]);
				sum=0;
			}
			else sum=cur[tmp[i]]+sum-p; 
		}

		if (take<mintake){
			mintake=take;
			minback=sum;
			for (int i=step;i>=1;i--) ans[i]=tmp[i];
			ans[0]=step;
		}else if (take==mintake && sum<minback){
			mintake=take;
			minback=sum;
			for (int i=step;i>=1;i--) ans[i]=tmp[i];
			ans[0]=step;
		}
		return;
	}
	for (int i=0;i<pre[endx].size();i++){
		Dfs(pre[endx][i],step+1);
	}
} 
int main() {
//	freopen("datain.txt","r",stdin);
	init();
	Dijkstra();
	Dfs(endx,1);
	cout<<mintake<<" 0";
	for (int i=ans[0]-1;i>=1;i--) cout<<"->"<<ans[i];
	cout<<" "<<minback<<endl; 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值