机试算法讲解: 第38题 求Dijkstra最短路径及花费

来源:互联网 发布:mac jenkins 安装 编辑:程序博客网 时间:2024/06/11 06:57
/*问题: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 21 2 5 62 3 4 51 30 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 1000000using 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;//设置初始花费为0int 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;}

0 0
原创粉丝点击