入门图论、图论的一些基本概念及实战

基本概念

图就是有N个顶点和M条边组成的集合。图分为有向图和无向图,如果给图的每条边规定一个方向,那么得到的图称为有向图,其他边也称为有向边。在有向图中,与一个点相关联的边有出边和入边之分,而与一个有向边关联的两个点也有始点和终点之分。边没有方向的图称为无向图。存储图的方式用邻接矩阵。

主要思想

首先是深度优先遍历,它的主要思想是:

首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问过。即沿着图的某一条分支遍历直到末端,然后回溯,再沿着另一条分支进行同样的遍历,直到所有的顶点都被访问为止。

接着是广度优先遍历,它的主要思想是:

首先以一个未被访问过的顶点作为起始顶点,访问其所有相邻的顶点,然后对每个相邻的顶点,再访问它们相邻的未被访问过的顶点,直到所有顶点都被访问过,遍历结束。

实战

例题1-无向图的广深优先遍历

利用邻接矩阵存储图,分别用深度优先遍历和广度优先遍历图。
在这里插入图片描述

代码实现:

#include<bits/stdc++.h>
using namespace std;
int n,m,a,b; //n为点,m为边 
int e[51][51],book[51];
int ans;
void dfs(int cur)
{
    
    
	printf("%d ",cur);
	ans++;
	if(ans==5) return;
	for(int i=1;i<=n;i++){
    
    
		if(e[cur][i]==1&&book[i]==0){
    
    
			book[i]=1;
			dfs(i);
		}
	}
}
int main()
{
    
    
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
    
    
		for(int j=1;j<=n;j++){
    
    
			if(i==j) e[i][j]=0;
			else e[i][j]=99999999;
		}
	} 
	for(int i=1;i<=m;i++){
    
    
		scanf("%d%d",&a,&b);
		e[a][b]=1;
		e[b][a]=1;
	}
	
	book[1]=1;
	dfs(1);
	
	return 0;
}

结果:
在这里插入图片描述

代码实现:

#include<bits/stdc++.h>
using namespace std;
int n,m,a,b,head=1,tail=1;
int e[51][51],book[51],que[2501];
int main()
{
    
    
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
    
    
		for(int j=1;j<=n;j++){
    
    
			if(i==j) e[i][j]=0;
			else e[i][j]=99999999;
		}
	}
	
	for(int i=1;i<=m;i++){
    
    
		scanf("%d%d",&a,&b);
		e[a][b]=1;
		e[b][a]=1;
	}
	
	que[tail]=1;
	book[que[tail]]=1;
	tail++;
	
	while(head<tail){
    
    
		
		int	cur=que[head];
		for(int i=1;i<=n;i++){
    
    
			if(e[cur][i]==1&&book[i]==0){
    
    
				book[i]=1;
				que[tail]=i;
				tail++;
			}
		}
		
		head++;
		
		if(tail>n) break;
	}
	
	for(int i=1;i<tail;i++){
    
    
		printf("%d ",que[i]);
	}
	return 0;
}

结果:
在这里插入图片描述

例题2–有向图的深度优先遍历(城市地图)

代码实现:

#include<bits/stdc++.h>
using namespace std;
int n,m,a,b,c;
int e[51][51],book[51];
int mi=99999999,ans;
void dfs(int cur)
{
    
    
	if(cur==n){
    
    
//		printf("%d\n",ans);
		if(mi>ans) mi=ans;
		return;
	}
	for(int i=1;i<=n;i++){
    
    
		if(e[cur][i]!=0&&e[cur][i]!=99999999&&book[i]==0){
    
    
			book[i]=1;
			ans+=e[cur][i];
			dfs(i);
			book[i]=0;
			ans-=e[cur][i];
		}
	}
}
int main()
{
    
    
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
    
    
		for(int j=1;j<=n;j++){
    
    
			if(i==j) e[i][j]=0;
			else e[i][j]=99999999;
		}
	}
	
	for(int i=1;i<=m;i++){
    
    
		scanf("%d%d%d",&a,&b,&c);
		e[a][b]=c;
	}
	
	book[1]=1;
	dfs(1);
	printf("%d",mi);
	return 0;
}

/*
5 8
1 2 2
1 5 10
2 3 3
2 5 7
3 1 4
3 4 4
4 5 5
5 3 3
9
*/ 

例题3–最少转机

首先是深度优先遍历,代码实现:

#include<bits/stdc++.h>
using namespace std;
int n,m,a,b,p,q;
int e[51][51],book[51];
int mi=99999999,ans;

void dfs(int cur)
{
    
    
	if(cur==q){
    
    
		if(mi>ans) mi=ans;
		return;
	}
	for(int i=1;i<=n;i++){
    
    
		if(e[cur][i]==1&&book[i]==0){
    
    
			book[i]=1;
			ans++;
			dfs(i);
			ans--;
			book[i]=0;
		}
	}
}

int main()
{
    
    
	scanf("%d%d%d%d",&n,&m,&p,&q);
	for(int i=1;i<=n;i++){
    
    
		for(int j=1;j<=n;j++){
    
    
			if(i==j) e[i][j]=0;
			else e[i][j]=99999999;
		}
	}
	
	for(int i=1;i<=m;i++){
    
    
		scanf("%d%d",&a,&b);
		e[a][b]=1;
		e[b][a]=1;
	}
	
	book[1]=1;
	dfs(p);
	
	printf("%d",mi);
	return 0;
}

接着是广度优先遍历,代码实现:

#include<bits/stdc++.h>
using namespace std;
int n,m,p,q;
int a,b,head=1,tail=1,flag;
int e[51][51],book[51];
struct note{
    
    
	int x;
	int step;
}que[2501];
int main()
{
    
    
	scanf("%d%d%d%d",&n,&m,&p,&q);
	for(int i=1;i<=n;i++){
    
    
		for(int j=1;j<=n;j++){
    
    
			if(i==j) e[i][j]=0;
			else e[i][j]=99999999;
		}
	}
	
	for(int i=1;i<=m;i++){
    
    
		scanf("%d%d",&a,&b);
		e[a][b]=1;
		e[b][a]=1;
	}
	
	que[tail].x=p;
	book[que[tail].x]=1;
	que[tail].step=0;
	tail++;
	
	while(head<tail){
    
    
		
		
		for(int i=1;i<=n;i++){
    
    
			
			if(e[que[head].x][i]==1&&book[i]==0){
    
    
				book[i]=1;
				que[tail].x=i;
				que[tail].step=que[head].step+1;
				tail++;
			}
			
			if(que[tail-1].x==q){
    
    
				flag=1;
				break;
			}
		}
		if(flag) break;
		head++;
	}
	printf("%d",que[tail-1].step);
	return 0;
}

好啦,图论到此正式入门啦!

猜你喜欢

转载自blog.csdn.net/qq_45735298/article/details/108149092