欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

图 (Dijkstra)

程序员文章站 2022-03-03 11:19:36
...

有向图代码

无向图代代码

邻接矩阵比较简单就直接开一个二维数组就OK

邻接表可以用vector,因为vector是个变长数组嘛,

vector<int> Adj[N];

可以设置出度邻接表,或者入度邻接表

如果需要权值。那就弄个结构体嘛

struct Node{
	int v;	//边的终点编号 
	int w;	//边权 
};
vector<Node> Adj[N];

入队

Node temp;
temp.v = 3;
temp.w = 4;
Adj[1].push_back(temp); 

+构造函数后

struct Node{
	int v;	//边的终点编号 
	int w;	//边权 
	Node(int _v, int _w) : v(_v), w(_w){}
};
Adj[1].push_back(Node(3, 4));

连通分量无向图中,两个顶点之间可以互相到达,那么就称这两个顶点连通,如果图G(V, E)的任意两个顶点都强连通,则称图G为强连通图,否则称G为非连通图,且称其中的极大连通子图为连通分量。

强连通分量:有向图中,如果两个顶点可以各自通过一条有向路径到达另一个顶点,就称这两个顶点强联通,如果图G(V,E)的任意两个顶点都是强连通,则图G为强联通图(还有单向连通,弱连通)强连通(一条回路)单向连通(一条通路)弱连通(不是上面两种情况),如果G非强连通,称其中的极大强连通子图为强连通分量。

建议画图

1)邻接矩阵版本DFS

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(vis[v] == false && G[u][v] != INF){
			DFS(v, depth + 1);
		}
	}
} 
void DFSTrave(){
	for(int u = 0; u < n; u++){
		if(vis[u] == false){
			DFS(u, 1);
		}
	}
} 

2)邻接表版DFS (vector)

vector<int> Adj[MAXV];
int n;
bool vis[MAXV] = {false};
void DFS(int u, int depth){
	vis[u] = true;
	for(int i = 0; i < Adj[u].size(); i++){
		int v = Adj[u][i];
		if(vis[v] == false){
			DFS(v, depth + 1);
		}
	}
}
void DFSTrave(){
	for(int u = 0; u < n; u++){
		if(vis[u] == false){
			DFS(u, 1);
		}
	}
} 

伪代码

DFS(u){
	vis[u] = true;
	for(从u出发能到达的所有顶点v){
		if(vis[v] == false){
			DFS(v);
		} 
	}
}
DFSTrave( G ){
	for(G的所有顶点u){
		if(vis[u] == false){
			DFS(u);		//访问 u所在的连通区域 
		} 
	} 
}

1)邻接矩阵 BFS

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

void BFS(int u){
	queue<int> q;
	q.push(u);
	inq[u] = true; 	//inq[]数组是判断是否已经入过队,而不是访问过没有。
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int v = 0; v < n; v++){
			if(inq[v] == false && G[u][v] != INF){
				q.push(v);
				inq[v] = true;
			}
		}
	}	 
} 

2)邻接表BFS

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

void BFS(int u){
	queue<int> q;
	q.push(u);
	inq[u] = true;
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int i = 0; i < Adj[u].size(); i++){
			int v = Adj[u][i];
			if(inq[v] == false){
				q.push(v);
				inq[v] = true;
			}
		}
	}
}

遍历图

void BFSTrave(){
	for(int u = 0; u < n; u++){
		if(inq[u] == false){
			BFS(u);
		}
	}
}

伪代码

BFS(u){
	queue q;
	inq[u] = true;
	while(q非空){
		取出队首元素u进行访问
		for(从u出发可达到的所有顶点v){
			if(inq[v] == false){
				将v入队;
				inq[v] = true; 
			}
		} 
	} 
}

稍微拓展,比如有时记录层数,或者记录步数。

我们需要用到结构体

struct Node {
	int v;	//顶点编号 
	int layer;	//顶点层号 
};

我们用邻接表的BFS实现下,矩阵一样的。

vector<Node> Adj[N];

解释下,如果当前层号为L,那么它所有出边的终点的层号都为L + 1,

void BFS(int s){
	queue<Node> q;
	Node start;
	start.v = s;
	start.layer = 0;
	q.push(start);
	inq[start.v] = true;
	while(!q.empty()){
		Node topNode = q.front();
		q.pop();
		int u = topNode.v;
		for(int i = 0; i < Adj[u].size(); i++){
			Node next = Adj[u][i];
			next.layer = topNode.layer + 1;
			if(inq[next.v] == false){
				q.push(next);
				inq[next.v] = true;
			}
		}
	}
} 

 

相关标签: