zoukankan      html  css  js  c++  java
  • PAT Advanced 1030 Travel Plan (30) [Dijkstra算法 + DFS,最短路径,边权]

    题目

    A traveler’s map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.
    Input Specification:
    Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (<=500) is the number of cities (and hence the cities are numbered from 0 to N-1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:
    City1 City2 Distance Cost
    where the numbers are all integers no more than 500, and are separated by a space.
    Output Specification:
    For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.
    Sample Input
    4 5 0 3
    0 1 1 20
    1 3 2 30
    0 3 4 10
    0 2 2 20
    2 3 1 20
    Sample Output
    0 2 3 3 40

    题意

    地图上显示了城市间高速公路的距离和费用,计算起点到终点距离最短的路线,如果有多条距离最短路线,取费用最低的最短路线

    题目分析

    已知图的顶点、边、两种边权(距离和费用),求单源带权最短路径,要求距离最短,若距离最短路径有多条,取费用最低的最短路径

    解题思路

    1. 存储图信息
      邻接矩阵
      邻接表
    2. 求最短路径
      2.1 dijkstra算法,求距离最短路径的同时,求出距离最短并且费用最少的最短路径
      2.2 dijkstra算法,求出所有距离最短路径并存储,dfs遍历所有距离最短路径,求出距离最短并且费用最少的最短路径

    int gw[maxn][maxn] //记录边权-距离
    int ct[maxn][maxn] //记录边权-费用
    int dist[maxn] //dijkstra记录从源点到其他顶点的最短距离
    int path[maxn] //dijskstra记录最短距离路径
    int act[maxn] //dijskstra记录从源点到其他顶点的最少费用
    int col[maxn] //标记已收集到最短路径中的顶点

    1. 打印最短路径
      3.1 利用栈(先进后出)
      3.2 dfs

    Code

    Code 01(邻接矩阵 dijskstra求距离最短费用最少路径)

    #include <iostream>
    #include <stack>
    using namespace std;
    const int maxn=510;
    const int INF=0x7fffffff;
    int n,s,d,gw[maxn][maxn],ct[maxn][maxn];// gw边权-距离;ct边权-费用
    int dist[maxn],path[maxn],act[maxn]; //act 总边权-总费用;
    int col[maxn];//col 已收集到最短路径标记
    /* dijkstra 求单源带权最短路径 */
    void dijkstra(int x) {
    	/*1 初始化*/
    	fill(dist,dist+maxn,INF);
    	fill(act,act+maxn,INF);
    	fill(path,path+maxn,-1);
    	dist[x]=0;
    	act[x]=0;
    	for(int j=0; j<n; j++) {
    		/*2 查找最小dist*/
    		int mind=INF,min=-1;
    		for(int i=0; i<n; i++) {
    			if(col[i]==0 && dist[i]<mind) {
    				mind=dist[i];
    				min=i;
    			}
    		}
    		if(min==-1||min==d)break;
    		col[min]=1;
    		/*3 最小路径*/
    		for(int i=0; i<n; i++) {
    			if(gw[min][i]==0||col[i]==1)continue;
    			if(dist[i]>dist[min]+gw[min][i]) {
    				dist[i]=dist[min]+gw[min][i];
    				path[i]=min;
    				act[i]=act[min]+ct[min][i];
    			} else if(dist[i]==dist[min]+gw[min][i]&&act[i]>act[min]+ct[min][i]) {
    				path[i]=min;
    				act[i]=act[min]+ct[min][i];
    			}
    		}
    	}
    }
    /* 打印最短路径 方法一*/
    void dfs(int y) {
    	if(y==-1)return;
    	dfs(path[y]);
    	printf("%d ",y);
    }
    /* 打印最短路径 方法二*/
    //void ppt(int y) {
    //	stack<int> sk;
    //	int p=y;
    //	while(p!=-1) {
    //		sk.push(p);
    //		p=path[p];
    //	}
    //	while(!sk.empty()) {
    //		printf("%d ",sk.top());
    //		sk.pop();
    //	}
    //}
    int main(int argc,char * argv[]) {
    	int m,a,b;
    	scanf("%d %d %d %d",&n,&m,&s,&d);
    	for(int i=0; i<m; i++) {
    		scanf("%d %d",&a,&b);
    		scanf("%d",&gw[a][b]);
    		scanf("%d",&ct[a][b]);
    		gw[b][a]=gw[a][b];
    		ct[b][a]=ct[a][b];
    	}
    	dijkstra(s);
    	dfs(d);
    //	ppt(d);
    	printf("%d %d",dist[d],act[d]);
    	return 0;
    }
    

    Code 02(邻接矩阵 dijkstra求最短距离路径 dfs求最少费用路径)

    #include <iostream>
    #include <vector>
    using namespace std;
    const int INF=0x7fffffff;
    const int maxn = 510;
    int gw[maxn][maxn],ct[maxn][maxn];
    int dist[maxn],path[maxn],act[maxn],col[maxn];
    int n,m,s,d,minct=INF;
    vector<int> pre[maxn],tempth,fp;
    void dijkstra(int v) {
    	fill(dist,dist+maxn,INF);
    	fill(path,path+maxn,-1);
    	fill(act,act+maxn,INF);
    	dist[v]=0;
    	act[v]=0;
    	for(int i=0; i<n; i++) {
    		int min=-1,mind=INF;
    		for(int j=0; j<n; j++) {
    			if(col[j]==0&&dist[j]<mind) {
    				mind=dist[j];
    				min=j;
    			}
    		}
    		if(min==-1||min==d)break;
    		col[min]=1;
    		for(int j=0; j<n; j++) {
    			if(gw[min][j]==0||col[j]==1)continue;
    			if(dist[min]+gw[min][j]<dist[j]) {
    				dist[j]=dist[min]+gw[min][j];
    				path[j]=min;
    				pre[j].clear();
    				pre[j].push_back(min);
    			} else if(dist[min]+gw[min][j]==dist[j]) {
    				path[j]=min;
    				pre[j].push_back(min);
    			}
    		}
    	}
    }
    void dfs(int u) {
    	if(u==s) {
    		tempth.push_back(u);
    		int tempct=0;
    		for(int i=tempth.size()-1; i>=1; i--) {
    			tempct+=ct[tempth[i]][tempth[i-1]];
    		}
    		if(minct>tempct) {
    			minct=tempct;
    			fp = tempth;
    		}
    		tempth.pop_back();
    		return;
    	}
    	tempth.push_back(u);
    	for(int i=0; i<pre[u].size(); i++) {
    		dfs(pre[u][i]);
    	}
    	tempth.pop_back();
    }
    int main(int argc,char * argv[]) {
    	scanf("%d %d %d %d",&n,&m,&s,&d);
    	int a,b;
    	for(int i=0; i<m; i++) {
    		scanf("%d %d",&a,&b);
    		scanf("%d",&gw[a][b]);
    		scanf("%d",&ct[a][b]);
    		gw[b][a]=gw[a][b];
    		ct[b][a]=ct[a][b];
    	}
    	dijkstra(s);
    	dfs(d);
    	for(int i=fp.size()-1; i>=0; i--) {
    		printf("%d ",fp[i]);
    	}
    	printf("%d %d",dist[d],minct);
    	return 0;
    }
    

    Code 03(邻接表 dijskstra求距离最短费用最少路径)

    #include <iostream>
    #include <vector>
    using namespace std;
    const int maxn=510;
    const int INF=0x7fffffff;
    int n,s,d;// gw边权-距离;ct边权-费用
    int dist[maxn],path[maxn],act[maxn]; //act 总边权-总费用;
    int col[maxn];//col 已收集到最短路径标记
    struct node{
    	int v;
    	int sw; //距离 
    	int cw; //费用 
    }; 
    vector<node> g[maxn];
    /* dijkstra 求单源带权最短路径 */
    void dijkstra(int x) {
    	/*1 初始化*/
    	fill(dist,dist+maxn,INF);
    	fill(act,act+maxn,INF);
    	fill(path,path+maxn,-1);
    	dist[x]=0;
    	act[x]=0;
    	for(int j=0; j<n; j++) {
    		/*2 查找最小dist*/
    		int mind=INF,min=-1;
    		for(int i=0; i<n; i++) {
    			if(col[i]==0 && dist[i]<mind) {
    				mind=dist[i];
    				min=i;
    			}
    		}
    		if(min==-1||min==d)break;
    		col[min]=1;
    		/*3 最小路径*/
    		for(int i=0; i<g[min].size(); i++) {
    			node u=g[min][i];
    			if(col[u.v]==1)continue;
    			if(dist[u.v]>dist[min]+u.sw) {
    				dist[u.v]=dist[min]+u.sw;
    				path[u.v]=min;
    				act[u.v]=act[min]+u.cw;
    			} else if(dist[u.v]==dist[min]+u.sw&&act[u.v]>act[min]+u.cw) {
    				path[u.v]=min;
    				act[u.v]=act[min]+u.cw;
    			}
    		}
    	}
    }
    /* 打印最短路径 方法一*/
    void dfs(int y) {
    	if(y==-1)return;
    	dfs(path[y]);
    	printf("%d ",y);
    }
    /* 打印最短路径 方法二*/
    //void ppt(int y) {
    //	stack<int> sk;
    //	int p=y;
    //	while(p!=-1) {
    //		sk.push(p);
    //		p=path[p];
    //	}
    //	while(!sk.empty()) {
    //		printf("%d ",sk.top());
    //		sk.pop();
    //	}
    //}
    int main(int argc,char * argv[]) {
    	int m,a,b,sw,cw;
    	scanf("%d %d %d %d",&n,&m,&s,&d);
    	for(int i=0; i<m; i++) {
    		scanf("%d %d",&a,&b);
    		scanf("%d",&sw);
    		scanf("%d",&cw);
    		g[a].push_back({b,sw,cw});
    		g[b].push_back({a,sw,cw});
    	}
    	dijkstra(s);
    	dfs(d);
    //	ppt(d);
    	printf("%d %d",dist[d],act[d]);
    	return 0;
    }
    

    Code 04 (邻接表 dijkstra求最短距离路径 dfs求最少费用路径)

    因为该求解方法,dfs中需要根据顶点a,b寻找边,若使用邻接表,需要遍历g[a]的所有有关联的顶点,找到b的node
    非要使用邻接表可以使用map<int,node> g[maxn];

  • 相关阅读:
    帆软—ORA-28040: No matching authentication protocol;
    Vmware虚拟机三种网络模式详解(转)
    ABAP—权限对象设计及权限检查
    ABAP—SM30维护表时提示“客户XXX有“不可修改”的状态”
    ABAP—SM维护表及标题“+”处理
    NC—语义模型调用存储过程(转)
    ABAP—多页签SHEET、选项参数或block隐藏
    oracle—聚合函数(max、min、avg、sum、count)
    oracle—decode、nvl、rownum、like、all、any使用
    从零开始的react入门教程(七),react中的状态提升,我们为什么需要使用redux
  • 原文地址:https://www.cnblogs.com/houzm/p/12371932.html
Copyright © 2011-2022 走看看