机试算法讲解: 第38题 求Dijkstra最短路径及花费
2015-08-01 14:31
309 查看
/* 问题: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<10000,s!=t 输出:一行有两个数:最短距离及其花费。 输入: 3 2 1 2 5 6 2 3 4 5 1 3 0 0 输出: 9 11 关键: 1更改距离评判标准,如果距离相同时,花费少的最近 2出了Dist[i],还需要设置一个Cost[i]数组用来记录从源点到第i个节点之间的花费,在更新最短距离时加以限制,挑选最短距离时不需要用这个限制条件 3Dijkstra不适用权值为负的情况 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <vector> #define MAX 1000 //#define INT_MAX 1000000 using namespace std; typedef struct Edge { int _iNext; int _iDist; int _iCost; }Edge; bool Mark[MAX]; int Dist[MAX]; int Cost[MAX]; int main(int argc,char* argv[]) { int n,m; int i,j; while(EOF!=scanf("%d %d",&n,&m)) { if(0==n && 0==m) { break; } //初始化所有链表,置标记为未知,置距离为无穷大 vector<Edge> vecEdge[MAX]; for(i = 0 ; i < MAX; i++) { vecEdge[i].clear(); Mark[i] = false; Dist[i] = INT_MAX; Cost[i] = INT_MAX; } //获取每条边的输入信息 int a,b,d,p; for(i = 0 ; i < m ; i++) { scanf("%d %d %d %d",&a,&b,&d,&p); Edge edge; edge._iDist = d; edge._iCost = p; edge._iNext = b; vecEdge[a].push_back(edge); edge._iNext = a; vecEdge[b].push_back(edge); } //获取起始和终止节点 int s,t; scanf("%d %d",&s,&t); if(s==t || n <=1 || n > 1000 || m <=0 || m>= 100000) { break; } //初始化,设置s为源点 Mark[s] = true; Dist[s] = 0; Cost[s] = 0;//设置初始花费为0 int iNewP = s; //开始进行n-1趟遍历,先更新距离,然后选择最短距离的点,加入到已知结点集合中 for(i = 0 ; i < n ; i++) { //遍历新加入结点的所有邻接结点,看是否需要进行距离的更新 for(j = 0; j < vecEdge[iNewP].size() ; j++) { //先取出与该加入结点的邻接结点的信息 int iNext = vecEdge[iNewP][j]._iNext; int iCost = vecEdge[iNewP][j]._iCost; int iDist = vecEdge[iNewP][j]._iDist; //如果该邻接结点是属于已知集合,则跳过。因为已知节点的距离已经是最短的,无需更新 if(true==Mark[iNext]) { continue; } //如果从起始节点到邻接结点的距离为无穷大,或者从源点到新加入节点距离 + 新加入节点到邻接结点距离 < 从源点到邻接结点距离,则距离更新 //或者距离相同,但是花费变少了,也进行更新 if(-1==Dist[iNext] || Dist[iNewP] + iDist < Dist[iNext] || (Dist[iNewP] + iDist == Dist[iNext] && Cost[iNewP] + iCost < Cost[iNext])) { Dist[iNext] = Dist[iNewP] + iDist; Cost[iNext] = Cost[iNewP] + iCost; } } //更新完距离后,需要挑选距离最小的节点,共有n个节点 int minDist = 123123123,minCost = 123123123; for(j = 1 ; j <= n; j++) { //如果是属于已知集合的点,则无需挑选 if(true==Mark[j]) { continue; } //距离小则更新;如果距离相同,则花费少的也更新(这里不需要,因为已经在前面更新最短距离时做过限定了) if(Dist[j] < minDist )//|| (Dist[j]==minDist && Cost[j] < minCost)) { minDist = Dist[j]; minCost = Cost[j]; iNewP = j;//重新获取新的中间节点 } } Mark[iNewP] = true; } //打印 printf("%d %d\n",Dist[t],Cost[t]); } system("pause"); getchar(); return 0; }
相关文章推荐
- inDensity,inTargetDensity,inScreenDensity关系详解
- JavaScript中的枚举类型
- 2524 矩形A + B
- [Leetcode] Maximal Square
- 【练习笔记】剑指offer-面试题6 :重建二义树
- ANTLR Reference书摘
- HDU 2128Tempter of the Bone II(bfs + 保存每一步的图)
- hdu 1384 Intervals 差分约束系统
- MongoDB与Elasticsearch达到数据同步的一点尝试
- iOS alloc和new的区别与联系
- hdu 1384 Intervals 差分约束系统
- 只会左键断点?是时候试试这样那样断点了
- 学习AngularJS的一些资料及网站
- E - 尤文图斯
- windows下如何将本地项目push到github仓库
- UVa 10340 All in All
- ubuntu 如何创建新用户
- zedboard 8路拨码开关
- PreparedStatement 预编译
- 安装及使用vsftpd+ssl