图的存储

邻接矩阵

一般只适用于顶点数目不太大的题目(一般不超过1000)

邻接表

顶点数大于1000的题目

  • vector实现

开一个vector数组Adj[N],其中N为顶点个数

  • 如果邻接表只存储每条边的终点编号,而不存储边权,则vector中的元素类型可以直接定义为int
  • 如果需要存储边权,则把替换类型替换为结构体Node
strcut Node{
	int v, w;
	Node(int _v, int _w) : v(-v), w(_w) {}
}

//此时可以不定义临时变量即可实现加边操作
Adj[i].push_back(Node(3, 4));

图的遍历

DFS

  • 伪代码
DFS(u) { //访问顶点u
	vis[u] = true;  //设置u已被访问
	for(从u出发能到达的所有顶点v)   //枚举
		if(vis[v] = false)
			DFS(v);
}
DFSTrave(G) {
	for(G的所有顶点u)   //枚举
		if (vis[u] == false
			DFS(u);    //访问u所在的连通块
}
  • 邻接矩阵 版本
int n, G[maxn][maxn];  //n为顶点数,maxn为最大顶点数
bool vis[maxn] = {false};

void DFS(int u, int depth) {
    
    vis[u] = true; //设置u已被访问
    
    //如果需要对u进行一些操作,在此处进行
    
    for(int v = 0; v < n; v++) //枚举所有结点
        if(vis[v] == false && G[u][v] != INF) //若未曾访问,且u可到达v
            DFS(v, depth + 1);  //访问i,深度+1

}

void DFSTrave() { //遍历图G
    for(int u = 0; u < n; u++)
        if(vis[u] == false)
            DFS(u, 1);      //初始为第一层
}
  • 邻接表 版本
vector<int> Adj[maxn];  //图G的邻接表
int n; //n为顶点数
bool vis[maxn] = {false};

void DFS(int u, int depth) {
    
    vis[u] = true; //设置u已被访问
    
    //如果需要对u进行一些操作,在此处进行
    
    for(int i = 0; i < Adj[u].size(); i++) { //枚举所有结点
        int v = Adj[u][i];  //vector可按下标访问
        if(vis[v] == false)  //若未曾访问,且u可到达v
            DFS(v, depth + 1);  //访问i,深度+1
	}//for
}

void DFSTrave() { //遍历图G
    for(int u = 0; u < n; u++)
        if(vis[u] == false)
            DFS(u, 1);      //初始为第一层
}

BFS

  • 伪代码
BFS(u) { //遍历u所在的连通块
	queue q;   //定义队列
	将u入队列
	inq[u] = true;  //设置u已入队列
	while(q非空) {
		取出q的队首元素u进行访问;
		for(从u出发能到达的所有顶点v)
			if(inq[v] == false){  //若未曾加入队列
				将v入队列
				inq[v] = true; //标记v加入队列
			}
	}//while
}

BFSTrave() { //遍历图
	for(G的所有顶点u) 
		if(inq[u] == false)
			BFS(u);  //遍历u所在的连通块
}
  • 邻接矩阵 版本
int n, G[maxn][maxn]; //n为顶点数
bool inq[maxn] = {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 v = 0; v < n; v++) {
            if(inq[v] == false && G[u][v] != INF) {//未曾入队列,且可达
                q.push(v);
                inq[v] = true; //标记v已经入队列
            }
        }
    }//while
}

void BFSTrave() { //遍历图
	for(int u = 0; u < n; u++) 
		if(inq[u] == false)
			BFS(u);  //遍历u所在的连通块
}
  • 邻接表 版本
vector<int> Adj[maxn];  //图G的邻接表
int n; //n为顶点数
bool inq[maxn] = {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];  //vector可按下标访问
            if(inq[v] == false) {//未曾入队列
                q.push(v);
                inq[v] = true; //标记v已经入队列
            }
        }
    }//while
}

void BFSTrave() { //遍历图
	for(int u = 0; u < n; u++) 
		if(inq[u] == false)
			BFS(u);  //遍历u所在的连通块
}

注:**当题目要求输出**结点的层号时,只需把vector<>中存储的元素换成结构体即可,结构体中包括结点编号层号信息。遍历的同时更新层号信息,子节点是父节点结点的层号+1。结构体如下:

struct node {
	int v;
	int layer;
};

应用练习

Battle Over Cities(A1013)并查集和DFS两种实现

Deepest Root(A1021)

Head of a Gang(A1032)

Forwards on Weibo(A1076)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值