C Dijkstra algorithm Floyd algorithm expansion 07-Figure 6 Tourism planning (25 points)

07-Figure 6 Tourism planning (25 points)

With a self-driving travel route map, you will know the length of the expressway between cities and the tolls to be charged for the highway. Now you need to write a program to help visitors who come to consult to find a shortest path between the place of departure and the destination. If there are several paths that are the shortest, then the cheapest path needs to be output.

Input format:
Input description: The first line of the input data gives 4 positive integers N, M, S, and D, where N (2≤N≤500) is the number of cities. By the way, assume that the city number is 0 ~ ( N−1); M is the number of highways; S is the city number of the starting place; D is the city number of the destination. In the subsequent M lines, each line gives information about a highway, namely: City 1, City 2, Highway length, toll amount, separated by spaces in the middle, the numbers are all integers and do not exceed 500. Enter to ensure the existence of the solution.

Output format:
The length of the path and the total amount of charges are output in one line. The numbers are separated by spaces, and there can be no extra spaces at the end of the 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:

3 40

Solve problems the
shortest path
from a single source; in addition to the shortest path, the cheapest path should be obtained on this basis;

The dijkstra algorithm is
used for the shortest path of a single source. When the dijkstra algorithm is used, the adjacency matrix representation graph is more convenient;

Although it is slow to set up so many structure functions, debugging and modifying the code will be faster;
1. Set the graph structure
to change the Vertex to road type, with two member variables of distance and cost

#include<iostream>
using namespace std;
typedef struct road Vertex;
typedef int weighttype; 
#define MAX 501
#define INFINITY 65533

struct road{
	int distance;
	int cost;
};

typedef struct  GNode *ptrtoGNode;  //图结构 
struct GNode{
	int Nv;  //节点数
	int Ne;  //边数
	Vertex G[MAX][MAX]; //存放500个序号 
	int start;
	int end; 
};
typedef ptrtoGNode MGraph;

2. Initialize the graph function

MGraph CreateGraph(int n)
{
	MGraph Graph = new struct GNode;
	Graph->Nv=n;
	Graph->Ne=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
		{
			Graph->G[i][j].cost=INFINITY;
			Graph->G[i][j].distance=INFINITY;
}
	return Graph;
	//距离全部初始化为最大值 
 } 

3. Side structure

typedef struct ENode * ptrtoENode;
struct ENode{
	//边结构
	int V1;
	int V2;
	weighttype distance;
	weighttype cost; 
};
typedef ptrtoENode Edge;

4. Functions
for inserting graphs into edges Standard undirected graph interpolation

void InsertEdge(MGraph Graph,Edge E)
{
	Graph->G[E->V1][E->V2].cost=E->cost;
	Graph->G[E->V1][E->V2].distance=E->distance;
	
	Graph->G[E->V2][E->V1].cost=E->cost;
	Graph->G[E->V2][E->V1].distance=E->distance;
}

5. Construction function

MGraph BuildGraph()
{
	int N,M,S,D;
	cin>>N;
	 //s出发,d停止 
	MGraph Graph= CreateGraph(N);
	cin>>Graph->Ne>>Graph->start>>Graph->end;
	if(Graph->Ne!=0)
	for(int i=0;i<Graph->Ne;i++)
	{	
		Edge E=new struct ENode;
		cin>>E->V1>>E->V2>>E->distance>>E->cost;
		InsertEdge(Graph,E);
	}
	return Graph;
}

The above code has input operations and built a graph;
you can build an MGraph Graph to save; the
following uses the Dijkstra function to process the graph and output it;
note that the
Dijkstra function takes the unprocessed distance minimum every time; the
FindMinDist function , Get the index of e of the smallest distance starting from s; if all destinations have been processed, return ERROR value -1;

int FindMinDist(MGraph Graph,int dist[],int collected[])
{
	int MinV,V; //下标
	int MinDist = INFINITY;
	
	for(V=0;V<Graph->Nv;V++)
	{	//未收入且小于当前最小值 
		if(collected[V]==false && dist[V]<MinDist)
		{
			MinDist = dist[V];
			MinV=V; //保存下标 
		}
	 }
	 if(MinDist<INFINITY)
	 	return MinV;
	 else return -1; 
 } 

Dijkstra function
Initialize the dist list first, indicating the shortest distance from s to each city;
then initialize the cost, indicating the money drawn on the shortest distance path from s to each city;
then initialize the path, indicating s to each city The shortest distance path;
dist is initialized to the distance of each element of line s; borderless is INFINITY;
cost is initialized to the cost of each element of line s; borderless is INFINITY; the
initial starting distance and cost are both 0, because you The distance to yourself is 0, the cost is 0;
the starting point is collected;
start the cycle:
get the city index that has not been traversed in the s line;
income the city;
cycle the distance from the city to each S line city:
if another city Not included, and the distance between the two is <INFINITY (with edges):
1. Determine whether it is a negative edge-the negative edge cannot calculate the minimum value-fail to exit; (not used in this question)

	if(dist[V]+Graph->G[V][i].distance<dist[i])

S The distance from the shortest distance V to the edge of Vi through Vi is smaller than the current distance from i: updating the distance of i
also needs to update the cost; and the path (the path does not need to be saved in this question);
if the distance is equal-it costs more Small, but also updated;

bool Dijkstra(MGraph Graph, int s,int e) //S为起点 
{   //传入图,dist为距离列表,path为路径,s为节点
	int collected[MAX]; //表示放入的结点
	int V;
	int dist[MAX];
	int cost[MAX];
	int path[MAX];   //保存路径 
	
	for(int i=0;i<Graph->Nv;i++)
	{
		dist[i]=Graph->G[s][i].distance;   //距离
		cost[i]=Graph->G[s][i].cost;
		if (dist[i]<INFINITY)
			path[i]=s;   //i的上一个为s
		else 
			path[i]=-1;   //没有路 
		collected[i]=false;
	 } 
	 
	 dist[s]=0;   //起点收入集合 
	 cost[s]=0;
	 collected[s]=true;
	 
	 while(1)
	 {
	 	V=FindMinDist(Graph,dist,collected);
	 	if(V==-1)
	 		break;
	 	collected[V]=true;
	 	for( int i=0;i<Graph->Nv;i++)
	 		if(collected[i]==false && Graph->G[V][i].distance<INFINITY){
	 			if(Graph->G[V][i].distance<0)
	 				return false; //有负边——失败
				if(dist[V]+Graph->G[V][i].distance<dist[i])
				{
					dist[i]=dist[V]+Graph->G[V][i].distance; //更新dist[i]
					cost[i]=cost[V]+Graph->G[V][i].cost;
					path[i]=V;
				 }
				 //如果距离相等,花费更小; 
				 if(dist[V]+Graph->G[V][i].distance==dist[i]&&cost[V]+Graph->G[V][i].cost<cost[i]){
				 	dist[i]=dist[V]+Graph->G[V][i].distance; //更新dist[i]
					cost[i]=cost[V]+Graph->G[V][i].cost;
					path[i]=V;
				 } 
			 }
	 } //while 结束 
	 cout<<dist[e]<<" "<<cost[e]<<endl;
	 return true;
 } 

main function

int main()
{
	MGraph Graph= BuildGraph();
	bool t = Dijkstra(Graph,Graph->start,Graph->end);
	
}

Accidentally, I also made a floyd algorithm, the complexity is too high,
because of the construction specification, so I only need to change the main function and the floyd function.

void Floyd(MGraph Graph,Vertex D[][MAX]){
	for(int i=0;i<Graph->Nv;i++)
		for(int j=0;j<Graph->Nv;j++)
			D[i][j]=Graph->G[i][j];
			
	for(int k=0;k<Graph->Nv;k++)
		for(int i=0;i<Graph->Nv;i++)
			for(int j=0;j<Graph->Nv;j++)
			{	
				if(D[i][k].distance+D[k][j].distance<D[i][j].distance)
				{
					D[i][j].distance  = D[i][k].distance+D[k][j].distance;
					D[i][j].cost  = D[i][k].cost+D[k][j].cost;
				}
				if(D[i][k].distance+D[k][j].distance==D[i][j].distance
				&&D[i][k].cost+D[k][j].cost<D[i][j].cost)
				{
					D[i][j].distance  = D[i][k].distance+D[k][j].distance;
					D[i][j].cost  = D[i][k].cost+D[k][j].cost;
					}	
			}
}
//此时 
void output(MGraph Graph)
{
	Vertex D[MAX][MAX];
	Floyd(Graph,D);
	//此时D存放最短distance和最短cost;
	cout<<D[Graph->start][Graph->end].distance<<" "<<D[Graph->start][Graph->end].cost;
	
}

//
int main()
{
	MGraph Graph=BuildGraph();
	output(Graph);
}

Summary
In the case of the same distance, this problem adds an additional cost judgment;
Dijkstra algorithm: (if there is a negative edge, it will be invalid) if (Graph-> G [V] [W] <0)
requires a collected list, save the minimum found Point of value;
a dist list is required to save the shortest path from the current point to each other point, initialized to INFINITY ; the
method of calculating the shortest path from S to v is

for(int i=0;i<Graph->Nv;i++)
if(dist[i]+Graph->G[i][V] < dist[V])  dist[V]=dist[i]+Graph->G[i][V] ;

The complexity is O (N ^ 2), which is to find the complexity of the minimum value;
if the minimum heap is used, it can be reduced to O (NlogN);

Floyd algorithm: (the negative ring failure) IF (J == I && D [I] [J] <0) is negative back revolution
represented resulting graph adjacency matrix; infinity INFINITY is initialized to the maximum value ;
the On this basis, get the shortest distance of every two points;
no collected list

for(int k=0;k<Graph->Nv;k++)
	for(int i=0;i<Graph->Nv;i++)
		for(int j=0;j<Graph->Nv;j++)
			if(D[i][k]+D[k][j]<D[i][j])
				D[i][j]=D[i][k]+D[k][j];

When calling-to skip D [n] [n], and get to the minimum value of 0;
triple loop to get the minimum value of every two points-optimal sub-problem inheritance with dynamic programming;
complexity O ( N ^ 3);

If the cost needs to be calculated, the Dijkstra algorithm needs to add a list of costs and save the cost from the starting point to each other point;

Popularization of tourism planning issues:
How many shortest paths are required?
 count [s] = 1;
 If a more short circuit is found: count [W] = count [V] ; because W and V are only one edge apart, they are the same;
 If an equal length path is found: count [W] + = count [V] ; the number of appearance paths is the number of paths at a point before W;
the shortest path requiring the fewest number of edges
 count [s] = 0;
 if found More short circuit: count [W] = count [V] +1;
 If an equal length path is found: count [W] = count [V] +1;

Published 105 original articles · won praise 6 · views 4961

Guess you like

Origin blog.csdn.net/BLUEsang/article/details/105441950