PAT 备考第一天——图论算法(一)

版权声明:Dirichlet_zju https://blog.csdn.net/Dirichlet_zju/article/details/84546490

大纲:

必考考点:
1.图的定义和相关术语
2.图的存储(邻接矩阵和邻接表)
3.图的遍历(DFS和BFD)
4.最短路径算法
5.拓扑排序

非重点考点:
1.关键路径
2.最短路径中的Bellman-Ford和SPFA

甲级考纲以外的考点:
最小生成树算法

一、图的定义和相关术语
只列出术语:顶点(Vertex)、边(Edge)、权值、有向图、无向图、顶点的度、出度、入度、点权和边权

二、图的存储
1.邻接矩阵:Gij表示i点到j点的连线权值,因此无向图邻接矩阵对称
2.邻接表:链表的表头构成的数组,每一个链表表示与表头所对应顶点所有相连接的点

三、图的遍历
1.深度优先搜索(DFS, Depth First Searching)
1.1.遍历概述:沿着一条路径前进,直到无法继续前进,才退回到路径上距离当前顶点最近的还存在未访问分支顶点的岔道口,并前往访问那些未访问过的顶点,直到遍历整个图。
1.2.伪代码:

DFS(u){
	vis[u]=true;
	for(从u出发能到达的所有顶点v){
		if(vis[v]==false) DFS(v);
	}
}
DFSTraversal(G){
	for(G中所有顶点u){
		if(vis[u]==false) DFS(u);
	}
}

1.3. 邻接矩阵版代码与邻接表版代码

constint MAXV = 1000;
constint INF = 1000000000; //设置一个很大的数

邻接矩阵版

int n, G[MAXV][MAXV];
bool vis[MAXV] = {false};

void DFS(int u, int depth){
	vis[u] = true;
	for(int v=0; v<n; v++){
		if(G[u][v] != 0 && vis[v]==false)
			DFS(v, depth + 1);
	}
}

void DFSTraversal(){
	for(int u=0; u<n; u++){
		if(vis[u]==false) DFS(u,1);//1表示第一层
	}
}

邻接表版

//无权图
vector<int> Adj[MAXV];
//有权图: vector<Node> Adj[MAXV];
//struct Node{
//	int v;
//	int w;///权重
//	Node(int _v, _w) : v(_v), w(_w) {}		
//	此为构造函数,插入边代码可直接写作Adj[x].push_pack(Node(3,4));//插入顶点为3权重为4的一条边
//};
int n;
bool vis[MAXV]={false};
void DFS(int u, int depth){
	vis[u] = true;
	/*如果需要对u进行操作,就在此处插入*/
	for(int i=0; i<Adj[u].Size(); i++){//相比邻接矩阵少了非零判断
		if(vis[v]==false) DFS(v, depth+1);
	}
}
void DFSTraversal(){//与邻接矩阵没有区别
	for(int u=0; u<n; u++){
		if(vis[u]==false) DFS(u, 1);	
	}
}

2.广度优先搜索(BFS,Breadth First Search)
2.1.遍历概述

2.2.伪代码

BFS(u){
	queue q;
	q.enqueue(u);//入队
	inq[u]=true;//使u入队并标记
	while(q非空){
		取出q队列头m进行访问;
		for(m所有连接点v){
			if(inq[v]==false) {
				q.enqueue(v);
				inq[v]=true;
			}
		}
	}
}

BFSTraversal(){
	for(G的所有顶点u){
		if(inq[u]==false){
			BFS(u);
		}
	}
}

2.3.邻接矩阵版代码与邻接表版代码

const int MAXV=1000;
const int INF=1000000000;

邻接矩阵

int G[MAXV][MAXV];//定义邻接矩阵图
int n;//顶点数
bool inq[MAXV]={false};
void BFS(int u){
	queue<int> q;
	q.push(u);//入队并标记
	inq[u]=true;
	while(!q.empty()){//循环结束条件只有队列q为空
		int m=q.front();//取出队列头
		q.pop();
		for(int i=0; i<n; i++){//遍历每一行
			if(inq[i]==false && G[m][i]!=0){
				q.push(i);//入队并标记
				inq[i]=true;
			}
		}
	}
}
//遍历图中所有点
void BFSTraversal(){
	for(int i=0; i<n; i++){
		//没有被遍历过则BFS
		if(inq[i]==false) BFS(i);
	}
}

邻接表

vector<int> Adj[MAXV];//无权图
//vector<Node> Adj[MAXV];有权图这样表示
//struct Node{
//	int data;
//	int weight;
//	Node(int _data, int _weight) : data(_data), weight(_weight) {}//这样方便赋值,Node(1,2)表示点值为1,权重为2
//};
int n;//个数
bool inq[MAXV]={false};//访问情况

void BFS(int u){
	queue<int> q;
	q.push(u);
	inq[u]=true;
	while(!q.empty()){
		int m=q.front();
		q.pop();
		//区别在这里,注意小于的是Adj[m].size,需要考虑这是什么形状的邻接表??
		for(int i=0; i<Adj[m].size(); i++){
			int v = Adj[m][i];
			if(inq[v] ==false){
				q.push(v);
				inq[v]=true;
			}
		}
	}
}
//同邻接矩阵
void BFSTraversal(){
	for(int i=0; i<n; i++){
		//没有被遍历过则BFS
		if(inq[i]==false) BFS(i);
	}
}

猜你喜欢

转载自blog.csdn.net/Dirichlet_zju/article/details/84546490