其他分享
首页 > 其他分享> > 7-3 最短路径 (20 分)(分支限界+思路+详解)

7-3 最短路径 (20 分)(分支限界+思路+详解)

作者:互联网

一:题目

给定一个有N个顶点和E条边的无向图,顶点从0到N−1编号。请判断给定的两个顶点之间是否有路径存在。如果存在,给出最短路径长度。 这里定义顶点到自身的最短路径长度为0。 进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。 随后E行,每行给出一条边的两个顶点。每行中的数字之间用1空格分隔。 最后一行给出两个顶点编号i,j(0≤i,j<N),i和j之间用空格分隔。

输出格式:
如果i和j之间存在路径,则输出"The length of the shortest path between i and j is X.",X为最短路径长度, 否则输出"There is no path between i and j."。

输入样例1:

7 6
0 1
2 3
1 4
0 2
1 3
5 6
0 3

结尾无空行
输出样例1:

The length of the shortest path between 0 and 3 is 2.

结尾无空行
输入样例2:

7 6
0 1
2 3
1 4
0 2
1 3
5 6
0 6

结尾无空行
输出样例2:

There is no path between 0 and 6.

二:思路

分析:1.这个题没给边的权值,但我们通过示例可以大概知道默认的为 每条边的权值为1

思路:1.先判断输入的值之间是否有路径,可以通过DFS来遍历其中一个顶点的所有邻接点
如果另一个邻接点没有在其中,那么就说明 其是不通的
2.如果两个点是相连通的,那么我们接下来就是BFS遍历
3.我们将图的信息转换成树的结构,我们在遍历树的时候采用的就是BFS
1>:首先我们将给定的两个结点的其中一个结点入队,接下来,将其出队当作扩展结点
这个新节点(在树当中的)有自己路径,还有权值和,以及层数。
2>:然后就判断这个结点(树)是否已经到达了目标结点,如果到,那么判断这个结点
的路径和跟bestw的值看是否更新,
如果没到目标结点,判断其路径和跟已知bestw 如果比起大就进行剪枝操作
再接下来,就是开始遍历其邻接点入队操作。

4.注意代码中的 node.x[t] 这其中 t代表的是层数,node.x[t]代表的是图的一个结点号
在这里插入图片描述

三:上码

/**
	分析:1.这个题没给边的权值,但我们通过示例可以大概知道默认的为 每条边的权值为1 

    思路:1.先判断输入的值之间是否有路径,可以通过DFS来遍历其中一个顶点的所有邻接点
		   如果另一个邻接点没有在其中,那么就说明 其是不通的 
		 2.如果两个点是相连通的,那么我们接下来就是BFS遍历 
		 3.我们将图的信息转换成树的结构,我们在遍历树的时候采用的就是BFS
		    1>:首先我们将给定的两个结点的其中一个结点入队,接下来,将其出队当作扩展结点 
			  这个新节点(在树当中的)有自己路径,还有权值和,以及层数。
	      	2>:然后就判断这个结点(树)是否已经到达了目标结点,如果到,那么判断这个结点
			  的路径和跟bestw的值看是否更新,
			  如果没到目标结点,判断其路径和跟已知bestw 如果比起大就进行剪枝操作
			  再接下来,就是开始遍历其邻接点入队操作。	 
	 
	   4.注意代码中的 node.x[t] 这其中 t代表的是层数,node.x[t]代表的是图的一个结点号 
*/

#include<bits/stdc++.h>
using namespace std;

int INF = 999999;
int maps[11][11];//存图用的数组。 
int N,M;
int bestw = INF;
int cnt = 0;
int vis2[11] = {0};

struct Node{
	int x[100];//记录树的路径
	int layer;//记录层数
	int cl;//记录已经走过的路径长度 
}; 

bool operator<(const Node& a,const Node& b){
	return a.cl > b.cl;//升序处理 小的数在前面 
} 

//判断是否可达
void dfs(int a,int b){
	
	if(a == b){
		cnt = 1;
		return;
	}	
	vis2[a] = 1;
	for(int i = 0; i < N; i++){
		if(vis2[i] != 1 && maps[a][i] == 1){	
			dfs(i,b); 
		}
	} 
	
//	cout << "wyj";
} 
// 
//求取最短路径 
void bfs(int a,int b){
	
	priority_queue<Node>q; 
	
	Node node1;
	node1.cl = 0;
	node1.layer = 0;//我们是从第0层开始的 
	
	for(int i = 0; i < N; i++){//初始化路径 
		node1.x[i] = i; 
	}   
	
	node1.x[0] = a;
	
	q.push(node1);
	
	while(!q.empty()){	
	
		int vis[11] = {0};
		vis[a] = 1;
	
		Node newnode;//扩展结点 
		newnode = q.top();
		q.pop();
		
		int t1 = newnode.layer;//代表当前的层数 
		int t2 = newnode.x[t1];//代表当前所到达的结点号 
			
	    //比较该节点的路径中,是否到达了目标结点
		if(t2 == b) {
			if(newnode.cl < bestw){
				bestw = newnode.cl;
			}else{//到达目标结点 如果还未成功的话,那就不用继续往下遍历了 
				continue;
			}	
		}
		
		if(newnode.cl >= bestw)//进行剪枝操作 
			continue;
		
		//将其扩展结点的邻接点入队
		for(int j = 0; j < N; j++){
			
			if(vis[j] != 1 && newnode.cl + maps[t2][j] < bestw) {
				
				int flag = 1; 
				for(int k = 0; k < t1; k++){
					if(newnode.x[k] == j){
						flag = 0;		
					}	
				} 
				
				if(flag == 0) continue; //这里主要处理的就是  不让这个路径往回走 
				
				vis[j] = 1; 
				
				//我们创建一个新的结点(在排列树当中) 
				Node node2;
				node2.cl = newnode.cl + maps[t2][j];
				node2.layer = t1 + 1;
				
				for(int i = 0; i < N; i++){
					node2.x[i] = newnode.x[i];
				}		
				swap(node2.x[t1+1],j);//t1代表的是层数,node.x[t1]代表该层数所对应图当中的结点号 
				
				q.push(node2);			
			}			
		}		 
			
	} 	
} 

int main(){	 

	int target1,target2;//两个目标结点 
	cin >> N >> M;
	
	for(int i = 0; i < N; i++){
		for(int j = 0; j < N; j++){
			if(i == j){
				maps[i][j] = 0;
			}
			maps[i][j] = INF;
		}
	}
	 
	for(int i = 0; i < M; i++){
		int side1,side2;
		cin >> side1 >> side2;
		maps[side1][side2] = 1;
		maps[side2][side1] = 1;  
	}
	
	cin >> target1 >> target2; 
	
	dfs(target1,target2);
	
	if(cnt == 0){
	   cout << "There is no path between "<< target1 <<" and " << target2 << ".";
	} else{
	   bfs(target1,target2);
	   cout << "The length of the shortest path between "<<target1 << " and "<< target2<<" is "<< bestw<<".";	
	}
		
	
} 




//7 6
//0 1
//2 3
//1 4
//0 2
//1 3
//5 6
//0 6


//7 7
//0 1
//2 3
//1 4
//0 2
//1 3
//5 6
//4 5
//0 6


//7 7
//0 1
//2 3
//1 4
//0 2
//1 3
//5 6
//4 5
//6 2


//7 7
//0 1
//2 3
//1 4
//0 2
//1 3
//5 6
//4 5
//4 2



在这里插入图片描述

四:总结

分支限界如果只是会BFS,是远远不够的,即便我提前已经做过BFS的练习题了,其还是有一定 相当的难度,注意自己一定要画出响应的图解,开始帮助理解算法和写代码

随手拍照,跟着考研上凌晨自习,感触颇多,没有了所谓大家的卷,其实都是在为自己人生路去努力拼搏,太喜欢这种学习的氛围了,感觉像是回到了高中,那种简单纯碎的学习和快乐 加油 大家
在这里插入图片描述
在这里插入图片描述

标签:结点,20,cl,int,路径,详解,newnode,bestw,限界
来源: https://blog.csdn.net/qq_48508278/article/details/121447890