最短路径问题 HDU - 3790(迪杰斯特拉)

给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

Input

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)

Output

输出 一行有两个数, 最短距离及其花费。

Sample Input

3 2
1 2 5 6
2 3 4 5
1 3
0 0

Sample Output

9 11

这个还是个迪杰斯特拉,但是这个最短路有好几个元素来决定的,一个是起点到终点的距离,一个是花费最少,所以我们需要多考虑一个因素,就是花费,基本上与迪杰斯特拉的模板差不多,就是有点不一样。

就是在中间多判断了一步,当距离一样的时候,就是比较花费怎么样。

代码:

#include<iostream>
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn=1005;
const int inf = 0x3f3f3f3f;

int val[maxn][maxn];	   //地图权值 
int time2[maxn][maxn];     //地图时间 

int vis[maxn];       //标记 
int d1[maxn];		//权值 
int d2[maxn];       //时间 

int n,m;
void init()
{
	
	memset(vis,0,sizeof(vis));
	memset(d1,0,sizeof(d1));
	memset(d2,0,sizeof(d2));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		if(i==j)
			val[i][j]=time2[i][j]=0;
		else
			val[i][j]=time2[i][j]=inf;
	
}

int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		if(n==0&&m==0)
			break;	
			
			init();
			int a,b,d,time;
			for(int i=0;i<m;i++)
			{
				scanf("%d%d%d%d",&a,&b,&d,&time);
				if(val[a][b]>d)
				{
					val[a][b]=val[b][a]=d;
					time2[a][b]=time2[b][a]=time;
				}
			}
			int start,end;
			scanf("%d%d",&start,&end);
		for(int i=1;i<=n;i++)
			d1[i]=val[start][i];
		for(int i=1;i<=n;i++)
			d2[i]=time2[start][i];
		int pos;
			
		
		for(int i=0;i<=n;i++)
		{
			int minv=inf;
			for(int j=1;j<=n;j++)
			if(!vis[j]&&minv>d1[j])
			{
				pos=j;
				minv=d1[j];
			}
			vis[pos]=1;
			for(int j=1;j<=n;j++)
			{
				if(!vis[j]&&d1[j]>val[pos][j]+minv)
				{
					d1[j]=minv+val[pos][j];
					d2[j]=time2[pos][j]+d2[pos];
				}
				else if(!vis[j]&&d1[j]==val[pos][j]+minv)
				{
					if(d2[j]>time2[pos][j]+d2[pos])
						d2[j]=time2[pos][j]+d2[pos];
				}
				
			}
			
		}	
		
		printf("%d %d\n",d1[end],d2[end]);
	}
	
	
	
	return 0;
}
发布了123 篇原创文章 · 获赞 83 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/tsam123/article/details/89682263
今日推荐