vector<set<int>> &adj
时间: 2024-06-02 19:05:56 浏览: 113
vector<set<int>> &adj是一个引用类型的变量,它是一个存储set<int>元素的vector容器。其中,每个set<int>元素表示图中某个顶点与其邻居顶点之间的关系,set<int>内部存储该顶点的所有邻居顶点编号。通过vector容器可以轻松地存储整张图的邻接表,方便图算法的实现。
举例来说,假设有一张无向图,其中有4个顶点,编号分别为0、1、2、3,邻接关系如下所示:
0:1、2
1:0、2、3
2:0、1
3:1
那么,通过vector<set<int>> &adj来存储该无向图的邻接表时,adj对应的set<int>元素中存储1和2两个整数,adj对应的set<int>元素中存储0、2和3三个整数,以此类推。
相关问题
改进以下代码#include <iostream> #include <cstring> #include <algorithm> #include <set> #include <vector> using namespace std; const int maxn = 1010; set<int> Adj[maxn]; bool hs[maxn]; vector<int> path; int Nv,Ne,st; void Read() { cin >> Nv >> Ne >> st; for(int i=0;i<Ne;++i) { int u,v; cin >> u >> v; Adj[u].insert(v); Adj[v].insert(u); } } void dfs(int u) { hs[u] = 1; cout << u << ' '; for(auto v:Adj[u]) if(hs[v]==0) { path.push_back(v); //将这个节点加到path中 dfs(v); //递归 path.pop_back(); //递归完成以后,需要返回,这时就需要打印 // 返回时结点的信息,先删除尾元素,再打印 if(path.size()) //要判断path是否为空 cout << path.back() << ' '; } } int main() { Read(); dfs(st); int cnt=0; for(int i=1;i<=Nv;++i) cnt += hs[i]; //判断地图是否连通 cout << st ; if(cnt != Nv) puts(" 0"); return 0; }
这段代码是基于深度优先搜索(DFS)实现的地图遍历,对于小规模的地图遍历问题是可以使用的,但是若遇到大规模的地图遍历问题则会存在效率问题,因为该算法没有使用剪枝等优化方法,因此可能会出现重复遍历的情况。同时,该代码也没有进行错误处理,例如当输入的节点数或边数超过最大值时程序可能会崩溃。以下是对该代码的改进建议:
1. 使用邻接表存储图
该代码使用的是set存储图的节点,但是对于大规模的图来说,这种存储方式的效率并不高。可以使用邻接表来存储图,避免重复存储边信息,提高程序效率。
2. 使用剪枝优化
在DFS的过程中,可以使用剪枝来避免重复遍历相同的节点,提高程序效率。具体来说,可以使用一个布尔数组记录已经遍历过的节点,遇到已经遍历过的节点就跳过,避免重复遍历。
3. 添加错误处理
在读入节点数和边数时,应该进行错误处理,例如当输入的节点数或边数超过最大值时应该给出提示并退出程序。
4. 修改函数参数
在DFS函数中,应该将path参数传入函数中,而不是使用全局变量,这样可以避免在多线程环境下出现问题。
5. 简化代码逻辑
在DFS函数中,可以将打印节点信息的逻辑简化,避免使用额外的vector来记录遍历路径。可以在递归的过程中传递已遍历的节点信息,然后在返回时打印即可。
综上所述,以下是改进后的代码:
int choose; std::cout << "请选择数据集(1、小数据, 2、大数据,3、随机图 ,else: 自行输入):\n"; std::cin >> choose; FILE* fp = nullptr; switch (choose) { case 1: fp = freopen(R"(C:\Users\28492\Desktop\szu\算法\Project5\mediumDG.txt)", "r", stdin); break; case 2: fp = freopen(R"(C:\Users\28492\Desktop\szu\算法\Project5\largeG.txt)", "r", stdin); break; default: cout << "请输入样例:" << endl; break; } cin >> n >> e; adj.clear(), adj.resize(n); int tag = 1; for (int i = 0; i < e; ++i) { int x, y; cin >> x >> y; if (x > y) swap(x, y); if (x == y) { continue; } if (cir_edges.count({ x, y })) continue; adj[x].emplace_back(y), adj[y].emplace_back(x); cout << tag; edges[tag++] = {x,y}; //order[x][y] = tag - 1; //标记每个边对应的下标 cir_edges.insert({ x, y }); }
这段代码是一个读取图数据的过程,根据用户选择的数据集,从相应的文件中读取图的节点数n和边数e,然后按照边的起点和终点构建邻接表,并且将边存储在一个vector中。其中,adj是邻接表,用vector实现;tag是一个整数变量,用于计数;edges是一个vector,用于存储边;cir_edges是一个set,用于存储已经出现过的边,避免出现重复边。
这段代码有几个需要注意的地方:
1. 文件路径
在使用freopen函数打开文件时,需要传入文件的路径。需要确保文件路径是正确的,否则会打开失败。
2. 输入格式
读取图数据时,需要按照固定的格式读入节点数n和边数e,然后按照边的起点和终点读入每条边。需要确保输入格式正确,否则会出现意想不到的错误。
3. 边的存储
这段代码使用了一个vector来存储图的边,可以根据需要对边进行排序、查找等操作。需要确保边的起点和终点的数据类型与vector中定义的一致,否则会出现类型不匹配的错误。
4. 重复边的处理
在读取图数据的过程中,可能会出现重复的边,需要进行处理。这段代码使用了一个set来存储已经出现过的边,避免出现重复边。
阅读全文