图
对于图的遍历,可以用邻接表
和邻接矩阵
来实现。
因为图不同于树结构,图是存在非连续的。所以图无法运用链式结构。
图又有4种情况,分别对应有无权值,有无方向
- 有权无向图
- 有权有向图
- 无权无向图
- 无权有向图
图的表示方法
邻接表和邻接矩阵
运用邻接表:
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
因为图的各个区域的点的个数不同,所有无法用统一的二维数组,应该用向量数组
运用邻接矩阵:
int u,v;
scanf("%d%d",&u,&v);
g[u][v]=1;
g[u][v]=1;
两个点如果相互连接的话,其邻接矩阵的值就是1
在无向图里要两个都进行赋值1,而在有向图里就只需要赋值一次
所有在无向图里浪费了一半的空间
连通分量模型---求无向图组成的图的个数
对图进行遍历,求有几个区域
思路:
构建向量数组和颜色数组
向量数组用于储存关系,每个向量的头结点代表头,之后的表示与头结点相互连接的边
颜色数组用于存储颜色数值,不同的区域具有不同的颜色,相互连接,可以传递的结点具有相同的颜色数值
无向图,所以a对b,b也对a
建立向量数组,存储后,对颜色初始化
开始对n个结点查询,只要遇到color为初始值的结点就进行该结点的dfs
在dfs中运用栈,将该结点的边的结点进行压入栈且把这些结点的颜色值和其相连接的结点的颜色值变成父结点的颜色值
利用邻接表遍历图
>在函数的形参中适用后自增++的话,要等到函数结束后才执行
>也就是本题第一个颜色输出为1而不是2的原因
#include <iostream>
#include <cstdio>
#include <vector>
#include <stack>
using namespace std;
static const int MAX = 1005;
static const int NIL = -1;
int n,m;
vector<int> g[MAX];//1005个顶点的图的邻接表
int color[MAX];
void dfs(int r,int c){
stack<int>s;
s.push(r);
color[r]=c;//相互连接的结点拥有同样的颜色;
while(!s.empty()){
//u作为待处理的父连接点
int u=s.top();
s.pop();
for(int i=0;i<g[u].size();i++){
//v是待处理的子连接点
int v=g[u][i];
if(color[v]==NIL){
color[v]=c;
s.push(v);
}
}
}
}
void assignColor(){
int id=1;
//初始化
for(int i=0;i<n;i++){
color[i]=NIL;
}
for(int u=0;u<n;u++){
if(color[u]==NIL){
dfs(u,id++);
}
}
}
int main(){
//n个结点,m条边
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
assignColor();
//输出所有颜色
for(int i=0;i<n;i++){
printf("%d",color[i]);
}
return 0;
}
强连通分量---有向图中所有点都可以到达的
- 在有向图G中,如果两个点可以互相到达,则称这两个点
强连通
- 如果G中任意两个点可以互相到达,则称G是
强连通图