当前位置: 首页 > news >正文

星际旅行家(广度优先搜索+邻接表)

我对这两个其实都不是那么熟悉。

我们略微用一用。

1. 邻接表基本概念

邻接表(Adjacency List)是一种图的存储结构,它通过为每个顶点维护一个链表来存储该顶点的所有邻接顶点。

优点​:

  • 节省空间(特别是稀疏图)
  • 容易找到某个顶点的所有邻接顶点
  • 添加/删除边操作高效

缺点​:

  • 判断两个顶点是否相邻需要遍历链表
  • 相比邻接矩阵,某些操作效率较低

C++中邻接表的实现方式

2.1 使用vector<vector<int>>

这是最常用的实现方式,简洁高效:

vector<vector<int>> adj(n);  // n为顶点数// 添加边(无向图)
adj[u].push_back(v);
adj[v].push_back(u);// 添加边(有向图)
adj[u].push_back(v);

2.2 使用list<int>数组

list<int> *adj = new list<int>[n];// 添加边
adj[u].push_back(v);

2.3 使用结构体/类(带权图)

struct Edge {int to;int weight;
};vector<vector<Edge>> adj(n);// 添加带权边
adj[u].push_back({v, w});

3. 邻接表的基本操作

3.1 初始化

int n = 5; // 顶点数
vector<vector<int>> adj(n);

3.2 添加边

// 无向图
void addEdge(int u, int v) {adj[u].push_back(v);adj[v].push_back(u);
}// 有向图
void addDirectedEdge(int u, int v) {adj[u].push_back(v);
}

3.3 删除边

// 无向图删除边
void removeEdge(int u, int v) {// 删除u->vadj[u].erase(remove(adj[u].begin(), adj[u].end(), v), adj[u].end());// 删除v->uadj[v].erase(remove(adj[v].begin(), adj[v].end(), u), adj[v].end());
}

3.4 遍历邻接顶点

// 遍历顶点u的所有邻接顶点
for(int v : adj[u]) {cout << v << " ";
}

4. 邻接表的常见应用

4.1 图的遍历

DFS实现​:

vector<bool> visited(n, false);void dfs(int u) {visited[u] = true;for(int v : adj[u]) {if(!visited[v]) {dfs(v);}}
}

BFS实现​:

void bfs(int start) {vector<bool> visited(n, false);queue<int> q;q.push(start);visited[start] = true;while(!q.empty()) {int u = q.front();q.pop();for(int v : adj[u]) {if(!visited[v]) {visited[v] = true;q.push(v);}}}
}

4.2 拓扑排序

vector<int> topologicalSort() {vector<int> inDegree(n, 0);vector<int> result;queue<int> q;// 计算入度for(int u = 0; u < n; u++) {for(int v : adj[u]) {inDegree[v]++;}}// 入度为0的节点入队for(int u = 0; u < n; u++) {if(inDegree[u] == 0) {q.push(u);}}// 拓扑排序while(!q.empty()) {int u = q.front();q.pop();result.push_back(u);for(int v : adj[u]) {if(--inDegree[v] == 0) {q.push(v);}}}return result;
}

5. 性能优化技巧

  1. 预分配空间​:如果知道大概的边数,可以预先reserve空间

    for(auto& list : adj) {list.reserve(expected_edges_per_vertex);
    }
  2. 使用emplace_back​:避免临时对象构造

    adj[u].emplace_back(v);
  3. 使用数组代替vector​:对于固定大小的图,性能更好

    vector<int> adj[MAX_NODES];
  4. 使用前向星​:对于极大图,可以节省空间

    struct Edge {int to, next;
    } edges[MAX_EDGES];
    int head[MAX_NODES], edge_count;

6. 邻接表的变体

6.1 带权图的邻接表

struct Edge {int to;int weight;
};vector<vector<Edge>> adj(n);// 添加带权边
adj[u].push_back({v, w});

6.2 使用pair的邻接表

vector<vector<pair<int, int>>> adj(n); // pair<to, weight>// 添加带权边
adj[u].emplace_back(v, w);

6.3 链式前向星

const int MAXN = 100010;
const int MAXM = 200010;struct Edge {int to, next, w;
} edge[MAXM];int head[MAXN], cnt;void init() {memset(head, -1, sizeof(head));cnt = 0;
}void addEdge(int u, int v, int w) {edge[cnt].to = v;edge[cnt].w = w;edge[cnt].next = head[u];head[u] = cnt++;
}

7. 常见问题与解决方案

7.1 处理重复边

// 使用set代替vector
vector<set<int>> adj(n);// 添加边(自动去重)
adj[u].insert(v);
adj[v].insert(u);

7.2 处理重边(允许重复边)

// 直接使用vector即可
vector<vector<int>> adj(n);
adj[u].push_back(v); // 允许重复添加

7.3 快速查询边是否存在

// 使用unordered_set
vector<unordered_set<int>> adj(n);// 查询边u->v是否存在
if(adj[u].count(v)) {// 边存在
}

 

上面其实已经总结邻接表与DFS和BFS结合使用的实例了

那我们直接看题:

代码:
 

# include<iostream>
# include<vector>
# include<queue>using namespace std;int main()
{int n,m;cin>>n>>m;vector<vector<int>> arr(n+1);vector<int> visited(n+1,false);queue<int> q;int u,v;for(int i=0;i<m;i++){cin>>u>>v;arr[u].push_back(v);arr[v].push_back(u);}q.push(1);visited[1] = true;while(!q.empty()){int current = q.front();for(int i:arr[current]){if(!visited[i]){q.push(i);visited[i] = true;}}q.pop();}int unvisited = 0;for(int i=2;i<=n;i++){if(!visited[i]){unvisited++;}}cout<<unvisited<<endl;return 0;
}

ok,其实没有太大必要去详细讲解,你从头仔细看肯定可以看懂的,心静如水,相信自己!

相关文章:

  • 通俗理解线性与非线性、时变与时不变系统,和数值不稳定性机制
  • 使用Java制作贪吃蛇小游戏
  • PCB文件从 Allegro 24.1 降级保存为 Allegro 17.4版本格式
  • YOLOV8涨点技巧之DSS模块(一种轻量化火灾检测模型)
  • React声明式编程(手动控制,大型项目,深度定制)与Vue响应式系统(自动优化,中小型项目,快速开发)区别
  • 多行字符串文本?各式各样的字符串类型?字符和字符串?
  • GO 语言进阶之 时间处理和Json 处理
  • 实战设计模式之访问者模式
  • Hertz+Kitex快速上手开发
  • 揭开C语言指针的神秘面纱:地址、变量与“指向”的力量
  • 【Python 元祖】 Tuple 核心知识点
  • QT单例模式简单讲解与实现
  • Redis哨兵模式,CLUSTERDOWN Hash slot not server 解决
  • 整数反转(7)
  • 《1.1_3_2 电路交换、报文交换、分组交换的性能分析|精讲篇》
  • 性能优化关键:link、script和meta的正确打开方式
  • 网络基础学习
  • 【Linux网络】UDP套接字【实现英汉转化】
  • 探索容器技术:Docker与Kubernetes的实践指南
  • ​​IIS文件上传漏洞绕过:深入解析与高效防御​
  • 找个兼职做网站的/网络营销的特点有哪些特点
  • 企业门户定制网站建设公司/怎么自己搭建网站
  • linux操作怎么做网站/淘宝店铺如何推广
  • 上海最专业的网站建设公司/seo3的空间构型
  • 华企网络/关键词优化app
  • 怎么建设免费网站/广州现在有什么病毒感染