图 (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;
}
}
}
}
上一篇: DS图—图的邻接矩阵存储及度计算
下一篇: 广度优先算法