题目1008:最短路径问题

题目1008:最短路径问题

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:5386

解决:1717

题目描述:
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
输入:
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
输出:
输出 一行有两个数, 最短距离及其花费。
样例输入:
3 2
1 2 5 6
2 3 4 5
1 3
0 0
样例输出:
9 11
来源:
2010年浙江大学计算机及软件工程研究生机试真题
c++代码:
//1008 最短路径问题
//Dijkstra
#include<cstdio>
#include<vector>
#include<cstring>
#define INF 0x7FFFFFFF

using namespace std;
const int NMAX = 1000+1;

struct edge
{
	int next;
	int distance;
	int cost;

	edge(int b,int d,int p)
	{
		next=b,distance=d,cost=p;
	}
};
vector<edge> eg[NMAX];//记录连接点 

int dis[NMAX];
int cost[NMAX];
bool mark[NMAX];
vector<int> vt; //已选队列
 
void init()
{
	memset(dis,-1,sizeof(dis));//不可达 
	memset(cost,0,sizeof(cost));
	memset(mark,false,sizeof(mark));
	for(int i=1; i<NMAX; ++i)
		eg[i].clear();
	vt.clear();
}

int
main(void)
{
	int n,m;
	while(~scanf("%d%d",&n,&m) && n &&m)
	{
		init();
		while(m--)
		{
			int a,b,d,p;
			scanf("%d%d%d%d",&a,&b,&d,&p);
			eg[a].push_back(edge(b,d,p));
			eg[b].push_back(edge(a,d,p));
		}
		int start,end;
		scanf("%d%d",&start,&end);
		dis[start] = 0;
		mark[start] = true;
		vt.push_back(start);
		
		for(int i=1; i<=n; ++i)//n遍 
		{
			int min = INF;
			int minp = -1;
			int mincost = -1;
			int j = 0;
			while(j<vt.size())//已选入的进行遍历 
			{
				int cor = vt[j];
				int size = eg[cor].size();
				for(int k=0; k<size; ++k)
				{
					int tp = eg[cor][k].next;
					if(mark[tp]==false)
					{
						if((dis[cor]>=0 && dis[cor]+eg[cor][k].distance<min)
							|| (dis[cor]+eg[cor][k].distance==min &&
							cost[cor]+eg[cor][k].cost<mincost))//核心(最短距离,距离一样代价最短优先) 
						{
							min = dis[cor]+eg[cor][k].distance;
							minp = tp;
							mincost = cost[cor] + eg[cor][k].cost;
						}
					}
				}
				j++;
			}
			mark[minp] = true;
			dis[minp] = min;
			cost[minp] = mincost;
			vt.push_back(minp);
		} 
		
		printf("%d %d\n",dis[end],cost[end]);
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值