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];

  • 相关阅读:
    Elasticsearch源码加载到eclipse调试
    Elasticsearch基础教程
    关于JAVA EE项目在WEB-INF目录下的jsp页面如何访问WebRoot中的CSS和JS文件
    访问WEB-INF下的JSP (转载)
    SqlServer的代理问题
    SqlServer进行程序跟踪
    git简单的修改
    Linux部署项目
    网址仓库
    Linux基础
  • 原文地址:https://www.cnblogs.com/houzm/p/12371932.html
Copyright © 2011-2022 走看看