hdoj 3790 最短路径问题

最短路径问题

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 17986    Accepted Submission(s): 5394

Problem Description

给你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

 

思路:比求最短距离多了个最小花费,所以要多用一个数组来储存,更新最短路径时也要考虑两种情况。

 

 

代码1:dijkstra

 
#include<stdio.h>
#include<string.h>
#define MAXN 1000+10
#define INF 0x3f3f3f
int mapdis[MAXN][MAXN],mapmoney[MAXN][MAXN],vis[MAXN];
int n,m;
int low[MAXN],mon[MAXN];//存储路径距离,花费;
void init() //初始化;
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j)
			{
				mapdis[i][j]=0;
			    mapmoney[i][j]=0;
			}
			else
			{
				mapdis[i][j]=INF;
			    mapmoney[i][j]=INF;
			}
		}
	}
}
void dijkstra(int x)
{
	int i,j,min,next;
	memset(vis,0,sizeof(vis));
	for(i=1;i<=n;i++)
	{
		low[i]=mapdis[x][i];
		mon[i]=mapmoney[x][i];
	}
	vis[x]=1;
	for(i=2;i<=n;i++)
	{
		min=INF;
		for(j=1;j<=n;j++)
		{
			if(!vis[j]&&min>low[j])
			{
				min=low[j];
			    next=j;
			}
		}
		vis[next]=1;
		for(j=1;j<=n;j++) //更新low和mon;
		{
			if(!vis[j]&&low[j]>low[next]+mapdis[next][j])
			{
				low[j]=low[next]+mapdis[next][j];
				mon[j]=mon[next]+mapmoney[next][j];
			}
			if(!vis[j]&&low[j]==low[next]+mapdis[next][j]&&mon[j]>mon[next]+mapmoney[next][j])
			{
				low[j]=low[next]+mapdis[next][j];
				mon[j]=mon[next]+mapmoney[next][j];
			}
		}
	}
}
int main()
{
	int a,b,d,p,s,t;
	while(scanf("%d%d",&n,&m)!=EOF&&n|m)
	{
		init();
		while(m--)
		{
			scanf("%d%d%d%d",&a,&b,&d,&p);
			if(mapdis[a][b]>d)//先推断路径距离;
			{
				mapdis[a][b]=mapdis[b][a]=d;
				mapmoney[a][b]=mapmoney[b][a]=p;
			}
			if(mapdis[a][b]==d&&mapmoney[a][b]>p)//距离同样在推断花费。
			{
				mapdis[a][b]=mapdis[b][a]=d;
				mapmoney[a][b]=mapmoney[b][a]=p;
			}
		}
		scanf("%d%d",&s,&t);
		dijkstra(s);
		printf("%d %d\n",low[t],mon[t]);
	}
	return 0;
} 

代码2:spfa

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define INF 0x3f3f3f
#define MAXN 1000+10
#define MAXM 100000+10
using namespace std;
int low[MAXN],vis[MAXN],head[MAXN],mon[MAXN];//mon[MAXN]存储最小花费;
int n,m,top;
struct record
{
	int to,next,val,money;//money--花费;val--距离;
}edge[MAXM];
void init()
{
	top=0;
	for(int i=1;i<=n;i++)
	{
		head[i]=-1;
		vis[i]=0;
	}
}
void add(int a,int b,int d,int p)
{
	edge[top].to=b;
	edge[top].money=p;
	edge[top].val=d;
	edge[top].next=head[a];
	head[a]=top++;
}
void spfa(int x)
{
	int i;
	queue<int>q;
	for(i=1;i<=n;i++)
	{
		low[i]=INF;
		mon[i]=INF;
	}
	vis[x]=1;
	low[x]=0;
	mon[x]=0;
	q.push(x);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(i=head[u];i!=-1;i=edge[i].next)
		{
			int v=edge[i].to;
			if(low[v]>low[u]+edge[i].val)//先推断路径距离;
			{
				low[v]=low[u]+edge[i].val;
				mon[v]=mon[u]+edge[i].money;
				if(!vis[v])
				{
					vis[v]=1;
					q.push(v);
				}
			}
			if(low[v]==low[u]+edge[i].val&&mon[v]>mon[u]+edge[i].money)
			{              //路径距离同样时。取花费最小的
				low[v]=low[u]+edge[i].val;
				mon[v]=mon[u]+edge[i].money;
				if(!vis[v])
				{
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
}
int main()
{
	int i,a,b,d,p,s,t;
	while(scanf("%d%d",&n,&m)!=EOF&&n|m)
	{
		init();
		while(m--)
		{
			scanf("%d%d%d%d",&a,&b,&d,&p);
			add(a,b,d,p);
			add(b,a,d,p);
		}
		scanf("%d%d",&s,&t);
		spfa(s);
		printf("%d %d\n",low[t],mon[t]);
	}
	return 0;
}
时间: 2024-11-03 05:41:33

hdoj 3790 最短路径问题的相关文章

hdoj(3790) 最短路径

最短路径问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 13577    Accepted Submission(s): 4156 Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Input

HDOJ 3790 最短路径问题 【双权值】

题意:... 难点:如何处理两个权值. 分析:题意说如果最短路径有多个,那么取价值最低的那个,所以说价值随着路径在变,如果路径不相等那么就更新路径并且更新价值,反之,则判断价值是不是要更新. 代码: #include<stdio.h> #include<string.h> #define M 1002 #define INF 0x3f3f3f3f int mapp[M][M], mapd[M][M], n, m, di[M], dp[M];//mapd是路径 mapp是价值 boo

HDOJ 3790 最短路径问题(dijkstra算法)

最短路径问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 17968    Accepted Submission(s): 5385 Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Input

HDOJ 3790 双权值Dijkstra

1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <cstring> 5 using namespace std; 6 7 const int INF = 1000000; 8 const int MAXSIZE = 1005; 9 10 int map[MAXSIZE][MAXSIZE]; 11 int price[MAXSIZE][MAXSIZE]; 1

ACM: HDU 3790 最短路径问题-Dijkstra算法

HDU 3790 最短路径问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Input 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p.最后一行是

hdu 3790 最短路径问题(两个限制条件的最短路)

http://acm.hdu.edu.cn/showproblem.php?pid=3790 有两个条件:距离和花费.首先要求距离最短,距离相等的条件下花费最小. dijkstra,只是在判断条件时多考虑了花费. 注意重边. #include <stdio.h> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h>

hdu 3790 最短路径问题(双重权值,dijkstra算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790 题目大意:题意明了,输出最短路径及其花费. 需要注意的几点:(1)当最短路径相同时,输出最小花费!!! (2)更新路径的时候要注意更新花费. 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 const int INF=9999999; 5 int map[1010][1010],Min,n,co

HDU 3790 最短路径问题(SPFA || Dijkstra )

题目链接 题意 : 中文题不详述. 思路 :无论是SPFA还是Dijkstra都在更新最短路的那个地方直接将花费更新了就行,还有别忘了判重边,话说因为忘了判重边WA了一次. 1 //3790 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #include <queue> 7 const int INF = 1 <

【最短路+最小费用】hdu 3790 最短路径问题

Source : hdu 3790 最短路径问题 http://acm.hdu.edu.cn/showproblem.php?pid=3790 Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Input 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p.最后一行是两个数 s,t;起点s,终