1、邻接矩阵(vector二维数组)的DFS(递归实现)
- class Graph {
- public:
- Graph(int vertices);
- void addEdge(int from, int to);
- void DFS(int startVertex);
-
- private:
- int vertices;
- vector
int>> adjMatrix; - vector<bool> visited;
-
- void DFSRecursive(int vertex);
- };
-
- Graph::Graph(int vertices) {
- this->vertices = vertices;
- adjMatrix.resize(vertices, vector<int>(vertices, 0));
- visited.assign(vertices, false);
- }
-
- // 无向图
- void Graph::addEdge(int from, int to) {
- adjMatrix[from][to] = 1;
- adjMatrix[to][from] = 1; // For undirected graph
- }
-
- void Graph::DFS(int startVertex) {
- for (int i = 0; i < vertices; i++) {
- visited[i] = false;
- }
- DFSRecursive(startVertex);
- // 确保每一个点都能被遍历到,包括孤立点
- for (int i = 0; i < vertices; i++) {
- if(visited[i] == 0)
- DFSRecursive(i);
- }
- }
-
- void Graph::DFSRecursive(int vertex) {
- visited[vertex] = true;
- cout << "Visited vertex: " << vertex << endl;
-
- for (int i = 0; i < vertices; i++) {
- if (adjMatrix[vertex][i] == 1 && !visited[i]) {
- DFSRecursive(i);
- }
- }
- }
2、邻接表(vector实现)的DFS(栈实现)
- class Graph {
- public:
- Graph(int vertices);
- void addEdge(int from, int to);
- void DFS(int startVertex);
-
- private:
- int vertices;
- vector
int>> adjList; - };
-
- Graph::Graph(int vertices) {
- this->vertices = vertices;
- adjList.resize(vertices);
- }
-
- // 邻接表,每行长度不一。无向图
- void Graph::addEdge(int from, int to) {
- adjList[from].push_back(to);
- adjList[to].push_back(from);
- }
-
- void Graph::DFS(int startVertex) {
- vector<bool> visited(vertices, false);
- stack<int> s;
-
- visited[startVertex] = true;
- s.push(startVertex);
-
-
- while (!s.empty()) {
- int vertex = s.top();
- s.pop();
- cout << "Visited vertex: " << vertex << endl;
-
- for (int neighbor : adjList[vertex]) {
- if (!visited[neighbor]) {
- visited[neighbor] = true;
- s.push(neighbor);
- }
- }
- }
- }
3、邻接表(vector实现)的BFS(队列实现)
- class Graph {
- public:
- Graph(int vertices);
- void addEdge(int from, int to);
- void BFS(int startVertex);
-
- private:
- int vertices;
- vector
int>> adjList; - };
-
- Graph::Graph(int vertices) {
- this->vertices = vertices;
- adjList.resize(vertices);
- }
-
- // 无向图
- void Graph::addEdge(int from, int to) {
- adjList[from].push_back(to);
- adjList[to].push_back(from);
- }
-
- void Graph::BFS(int startVertex) {
- vector<bool> visited(vertices, false);
- queue<int> q;
-
- visited[startVertex] = true;
- q.push(startVertex);
-
- while (!q.empty()) {
- int vertex = q.front();
- q.pop();
- cout << "Visited vertex: " << vertex << endl;
-
- for (int neighbor : adjList[vertex]) {
- if (!visited[neighbor]) {
- visited[neighbor] = true;
- q.push(neighbor);
- }
- }
- }
- }
4、链式前向星DFS和BFS
- #include
- #include
- #include
-
- using namespace std;
-
- const int maxn = 100000; // 假定最大顶点数
-
- struct Edge {
- int to, w, next; // 终点,边权,同起点的上一条边的编号
- } edge[maxn]; // 边集
-
- int head[maxn]; // head[i],表示以i为起点的第一条边在边集数组的位置(编号)
- int cnt = 0; // 记录边的数量
- int n, m; // 顶点数和边数
-
- void init() {
- for (int i = 1; i <= n; i++) head[i] = -1;
- cnt = 0;
- }
-
- // 添加新边
- void add_edge(int u, int v, int w) {
- edge[cnt].to = v; // 终点
- edge[cnt].w = w; // 权值
- edge[cnt].next = head[u]; // 以u为起点上一条边的编号,也就是与这个边起点相同的上一条边的编号
- head[u] = cnt++; // 更新以u为起点上一条边的编号
- }
-
- void DFS(int startVertex) {
- vector<bool> visited(n + 1, false);
- stack<int> s;
-
- s.push(startVertex);
- visited[startVertex] = true;
-
- while (!s.empty()) {
- int vertex = s.top();
- s.pop();
- cout << "Visited vertex: " << vertex << endl;
-
- for (int j = head[vertex]; j != -1; j = edge[j].next) {
- int neighborVertex = edge[j].to;
- if (!visited[neighborVertex]) {
- s.push(neighborVertex);
- visited[neighborVertex] = true;
- }
- }
- }
- }
-
- void BFS(int startVertex) {
- vector<bool> visited(n + 1, false);
- queue<int> q;
-
- q.push(startVertex);
- visited[startVertex] = true;
-
- while (!q.empty()) {
- int vertex = q.front();
- q.pop();
- cout << "Visited vertex: " << vertex << endl;
-
- for (int j = head[vertex]; j != -1; j = edge[j].next) {
- int neighborVertex = edge[j].to;
- if (!visited[neighborVertex]) {
- q.push(neighborVertex);
- visited[neighborVertex] = true;
- }
- }
- }
- }
-
- int main() {
- cin >> n >> m;
- int u, v, w;
- init(); // 初始化
- for (int i = 1; i <= m; i++) // 输入m条边
- {
- cin >> u >> v >> w;
- add_edge(u, v, w); // 加边
- }
-
- int startVertex;
- cout << "Enter the starting vertex for DFS: ";
- cin >> startVertex;
- DFS(startVertex);
-
- cout << "Enter the starting vertex for BFS: ";
- cin >> startVertex;
- BFS(startVertex);
-
- return 0;
- }
5、无向图中,DFS判断连通块数量
- void DFS() {
- vis.resize(vertices);
- vis.assign(vertices, 0);
- unlinked_part = 0; // unlinked_part记录连通块数量
-
- for (int i = 0; i < vertices; i++) {
- if (vis[i] == 0) {
- DFSRecursive(i);
- unlinked_part++;
- }
- }
- }
- void DFSRecursive(int start) {
- vis[start] = 1;
- for (int i = 0; i < vertices; i++) {
- if (adjMatrix[start][i] == 1 && !vis[i]) {
- DFSRecursive(i);
- }
- }
- }
6、最小生成树
- class Graph {
- int vertices;
- vector
int>> adjMatrix; - map
int> ele1; - map<int, string> ele2;
- vector<int> vis;
- struct Closeedge {
- int from;
- int lowcost;
- };
-
- public:
- Graph() {}
-
- void build_Graph() {
- int n;
- cin >> n;
- this->vertices = n;
- adjMatrix.resize(vertices, vector<int>(vertices, INF));
-
- string* e = new string[n];
- for (int i = 0; i < n; i++) {
- cin >> e[i];
- ele1[e[i]] = i; // 记录节点字符对应的下标
- ele2[i] = e[i]; // 记录下标对应的字符
- }
- int m;
- cin >> m;
- edgenum = m;
- for (int i = 0; i < m; i++) {
- string from, to;
- int value;
- cin >> from >> to >> value;
- addEdge(ele1[from], ele1[to], value);
- }
- }
-
- void addEdge(int from, int to,int value) {
- adjMatrix[from][to] = 1;
- adjMatrix[to][from] = 1;
- }
-
-
- int Min(vector
vec) { - int k = -1, minn = INF;
- for (int i = 0; i < vertices; i++) {
- if (minn > vec[i].lowcost && vec[i].lowcost > 0) {
- minn = vec[i].lowcost;
- k = i;
- }
- }
- return k;
- }
-
- void Prim(string u) {
- int start = ele1[u]; // start为起始节点的下标
- int totlowcost = 0; // 记录最小权值和
- vector<int> ans; // 记录被选节点
- map<int, int> ans_cost; // 记录最小生成树每条路径的权值
- vector
closeedge(vertices) ; // 用于保存未选顶点的最小权值边closedge和这条边的另一个已选顶点 -
- for (int i = 0; i < vertices; i++) {
- closeedge[i] = { start, adjMatrix[start][i] }; // 初始化
- }
-
- closeedge[start].lowcost = 0;
- for (int i = 1; i < vertices; i++) {
- int k = Min(closeedge); // 选择当前已选节点到未选节点最小权值边对应的未选节点
- totlowcost += closeedge[k].lowcost;
- ans.push_back(k);
- ans_cost[k] = closeedge[k].lowcost;
- closeedge[k].lowcost = 0; // 已选顶点的最小权值边置0,后续将不再被选
-
- for (int j = 0; j < vertices; j++) {
- if (adjMatrix[k][j] < closeedge[j].lowcost) {
- closeedge[j] = Closeedge{ k, adjMatrix[k][j] }; // 更新未选顶点的最小权值边
- }
- }
- }
-
- cout << totlowcost << endl;
- for (int i = 0; i < vertices - 1; i++) {
- int k = ans[i];
- cout << ele2[closeedge[k].from] << " " << ele2[k] << " " << ans_cost[k] << endl;
- }
- }
-
- };
(2)Kruscal算法
- class MFSet {
- int n;
- vector<int> fa;
- public:
- MFSet(int n) {
- this->n = n;
- fa.resize(n);
- for (int i = 0; i < n; i++)
- fa[i] = i;
- }
- int find(int k) {
- if (fa[k] != k) return fa[k] = find(fa[k]);
- else return k;
- }
- void concat(int i, int k) {
- fa[fa[i]] = fa[k];
- for (int i = 0; i < n; i++)
- find(i);
- }
- int check() {
- int che = fa[0];
- for (int i = 0; i < n; i++) {
- if (che != fa[i]) return 0;
- }
- return 1;
- }
- };
-
- class Graph {
- int vertices;
- int edgenum;
- vector
int>> adjMatrix; - map
int> ele1; - map<int, string> ele2;
- vector<int> vis;
-
- struct edge {
- int from;
- int to;
- };
-
- public:
- Graph() {}
-
- void build_Graph() {
- int n;
- cin >> n;
- this->vertices = n;
- adjMatrix.resize(vertices, vector<int>(vertices, INF));
-
- string* e = new string[n];
- for (int i = 0; i < n; i++) {
- cin >> e[i];
- ele1[e[i]] = i; // 记录节点字符对应的下标
- ele2[i] = e[i]; // 记录下标对应的字符
- }
- int m;
- cin >> m;
- edgenum = m;
- for (int i = 0; i < m; i++) {
- string from, to;
- int value;
- cin >> from >> to >> value;
- addEdge(ele1[from], ele1[to], value);
- }
- }
-
- void addEdge(int from, int to,int value) {
- adjMatrix[from][to] = 1;
- adjMatrix[to][from] = 1;
- }
-
- void find_min(int &a, int &b, vector
int >>& vis_adj) { - int minn = INF;
- for (int i = 0; i < vertices; i++) {
- for (int j = i+1; j < vertices; j++) {
- if (minn > adjMatrix[i][j] && vis_adj[i][j] == 0) {
- minn = adjMatrix[i][j];
- a = i, b = j;
- }
- }
- }
- vis_adj[a][b] = 1;
- }
- void Kruscal(){
- vector
ans; // 记录最小生成树上的每条路径 - vector
int>> vis_adj; // 记录图中哪些边被选入最小生成树 - vis_adj.resize(vertices, vector<int>(vertices,0));
- MFSet mfset(vertices); // 并查集,记录每个节点所在集合
- int totlowcost = 0;
-
- int t = edgenum;
- while (t--) {
- int u, v;
- find_min(u, v,vis_adj); // 寻找未被选的最小权值边
-
- if (mfset.find(u) != mfset.find(v)) { // 两个节点属于不同集合,该边选入最小生成树的路径中
- mfset.concat(u, v);
- ans.push_back({ u,v });
- totlowcost += adjMatrix[u][v];
- }
-
- if (mfset.check() == 1) break; // 判断是否全部节点都属于同一集合,若是,则最小生成树已生成
- }
- if (mfset.check() == 0) {
- cout << -1 << endl;
- }
- else {
- cout << totlowcost << endl;
- for (int i = 0; i < ans.size(); i++) {
- cout << ele2[ans[i].from] << " " << ele2[ans[i].to] << " " << adjMatrix[ans[i].from][ans[i].to] << endl;
- }
- }
- }
-
- };
7、无向图DFS生成森林
- #include
- #include
- #include
- using namespace std;
-
- // 树节点
- struct treenode{
- int val;
- vector
son; // 存儿子节点指针 - treenode(int n) { val = n; }
- };
-
- vector
Root; // 存每棵树的树根 -
-
- class Graph {
- public:
- Graph(int vertices);
- void addEdge(int from, int to);
- void DFS();
- treenode* DFSRecursive(int vertex);
-
- private:
- int vertices;
- vector
int>> adjMatrix; - vector<bool> visited;
- };
-
- Graph::Graph(int vertices) {
- this->vertices = vertices;
- adjMatrix.resize(vertices, vector<int>(vertices, 0));
- visited.assign(vertices, false);
- }
-
- // 无向图
- void Graph::addEdge(int from, int to) {
- adjMatrix[from][to] = 1;
- adjMatrix[to][from] = 1;
- }
-
- void Graph::DFS() {
- visited.assign(vertices, 0);
-
- for (int i = 0; i < vertices; i++) {
- if (visited[i] == 0) {
- treenode* root;
- root=DFSRecursive(i);
- Root.push_back(root);
- }
- }
- }
-
- treenode* Graph::DFSRecursive(int vertex) {
- visited[vertex] = true;
- treenode* p = new treenode{ vertex };
-
- for (int i = 0; i < vertices; i++) {
- if (adjMatrix[vertex][i] == 1 && !visited[i]) {
- p->son.push_back(DFSRecursive(i));
- }
- }
- return p;
- }
-
- void show_tree(treenode *p) {
- cout << p->val;
- for (int i = 0; i < p->son.size(); i++) {
- if(p != nullptr)
- show_tree(p->son[i]);
- }
- }
-
- int main() {
- int n, m;
- cin >> n >> m;
- Graph G(n);
- for (int i = 0; i < m; i++) {
- int u, v;
- cin >> u >> v;
- G.addEdge(u, v);
- G.addEdge(u, v);
- }
- G.DFS();
-
- for (int i = 0; i < Root.size(); i++) {
- show_tree(Root[i]);
- cout << endl;
- }
- return 0;
- }
8、图的最短路径(迪杰斯特拉算法)
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define INF 0x3f3f3f3f
- using namespace std;
-
-
- class Graph {
- int vertices;
- vector
int>> adjMatrix; - map
int> ele1; - map<int, string> ele2;
- vector<int> vis;
-
- public:
- Graph() {}
-
- void build_Graph() {
- int n;
- cin >> n;
- this->vertices = n;
- adjMatrix.assign(vertices, vector<int>(vertices));
-
- string* e = new string[n];
- for (int i = 0; i < n; i++) {
- cin >> e[i];
- ele1[e[i]] = i; // 记录节点字符对应的下标
- ele2[i] = e[i]; // 记录下标对应的字符
- }
-
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++) {
- int tmp;
- cin >> tmp;
- addEdge(i, j, tmp);
- }
- }
- }
-
- void addEdge(int from, int to, int value) {
- adjMatrix[from][to] = value;
- }
-
- void Dijkstra() {
- vector
int>> path; // 记录起点到其他每个节点最短路径的路径 - path.resize(vertices);
- vis.assign(vertices, 0);
- vector<int> dis; // 记录起点到其他每个节点的最短路径距离
- dis.assign(vertices, INF);
-
- string start;
- cin >> start;
- int v = ele1[start];
- vis[v] = 1;
- dis[v] = 0;
- for (int i = 0; i < vertices; i++) {
- if(adjMatrix[v][i])
- {
- dis[i] = dis[v] + adjMatrix[v][i]; // 更新起点到其他点的最短路径距离
- path[i].push(v);
- }
- }
-
- for (int i = 0; i < vertices - 1; i++) {
- int Min = INF;
- for (int j = 0; j < vertices; j++)
- if (!vis[j] && Min > dis[j])
- {
- v = j;
- Min = dis[j];
- }
- vis[v] = 1;
-
- // 用当先被选中点来更新到最短路径距离
- for (int j = 0; j < vertices; j++) {
- if (!vis[j] && adjMatrix[v][j] && Min + adjMatrix[v][j] < dis[j]) {
- path[j] = path[v];
- path[j].push(v);
- dis[j] = Min + adjMatrix[v][j];
- }
- }
- }
-
- // 输出
- for (int i = 0; i < vertices; i++) {
- if (i != ele1[start]) {
- cout << start << "-" << ele2[i] << "-";
- if (dis[i] == INF) {
- cout << "-1" << endl;
- }
- else {
- cout << dis[i] << "----[";
- while(!path[i].empty()) {
- cout << ele2[path[i].front()] << " ";
- path[i].pop();
- }
- cout << ele2[i] << " ]" << endl;
- }
- }
- }
-
- }
- };
-
- int main() {
- int t;
- cin >> t;
- while (t--) {
- Graph G;
- G.build_Graph();
- G.Dijkstra();
- }
- }
9、判断图上是否出现正环,即环上所有的边相乘大于1(货币套汇问题)
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define INF 0x3f3f3f3f
- using namespace std;
-
-
- class Graph {
- int vertices;
- vector
double>> adjMatrix; - map
int> ele1; - map<int, string> ele2;
- vector<int> vis;
- vector
double>> check; // check记录从i到j节点路径权值的乘积 - int flag;
-
- public:
- Graph() {}
-
- void build_Graph() {
- int n;
- cin >> n;
- this->vertices = n;
- adjMatrix.assign(vertices, vector<double>(vertices, 0));
- int m;
- cin >> m;
-
- string* e = new string[n];
- for (int i = 0; i < n; i++) {
- cin >> e[i];
- ele1[e[i]] = i; // 记录节点字符对应的下标
- ele2[i] = e[i]; // 记录下标对应的字符
- }
-
- for (int i = 0; i < m; i++) {
- string from, to;
- double value;
- cin >> from >> value >> to;
- addEdge(ele1[from], ele1[to], value);
- }
-
- }
-
- void addEdge(int from, int to, double value) {
- adjMatrix[from][to] = value;
- }
-
-
- int DFS() {
- vis.assign(vertices, 0);
- for (int i = 0; i < vertices; i++) {
- for (int j = 0; j < vertices; j++) {
- if (i == j) check[i][j] = 1;
- else check[i][j] = 0;
- }
- }
- flag = 0;
-
- for (int i = 0; i < vertices; i++) {
- if (vis[i] == 0)
- DFSRecursive(i);
- if (flag == 1) return 1;
- }
- return 0;
- }
-
- void DFSRecursive(int vertex) {
- vis[vertex] = true;
-
- for (int i = 0; i < vertices; i++) {
-
- // adjMatrix[vertex][i] && vis[i] == 1 即表示存在环,
- // check[i][vertex] * adjMatrix[vertex][i]即从i到j节点路径权值的乘积*j到i权值的乘积 = 环上权值乘积
- if (adjMatrix[vertex][i] && vis[i]) {
- if (check[i][vertex] * adjMatrix[vertex][i] > 1) flag = 1;
- continue;
- }
- else if(adjMatrix[vertex][i]){
- for (int j = 0; j < vertices; j++) {
- check[j][i] = check[j][vertex] * adjMatrix[vertex][i];
- }
- DFSRecursive(i);
- }
- }
- }
-
- };
-
- int main() {
- int t;
- cin >> t;
- while (t--) {
- Graph G;
- G.build_Graph();
- if (G.DFS()) {
- cout << "YES" << endl;
- }
- else cout << "NO" << endl;
- }
- }
10、键路径-STL版(含拓扑排序)
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define INF 0x3f3f3f3f
- using namespace std;
-
-
- class Graph {
- int vertices;
- vector
int>> adjMatrix; - vector<int> ve; // 记录顶点的最早开始时间
- vector<int> vl; // 记录顶点的最晚开始时间
- stack<int> st_re; // 存AOE图的拓扑序列
- queue<int> q; // 用于处理AOE图的拓扑序列
- vector<int> init; // 记录节点入度
-
- public:
- Graph() {}
-
- void build_Graph() {
- int n;
- cin >> n;
- this->vertices = n;
- adjMatrix.assign(vertices, vector<int>(vertices, 0));
- init.assign(vertices, 0);
-
- int m;
- cin >> m;
- for (int i = 0; i < m; i++) {
- int u, v, e;
- cin >> u >> v >> e;
- adjMatrix[u][v] = e;
- init[v]++;
- }
- }
-
- void Topoorder() {
- for (int i = 0; i < vertices; i++) {
- if (init[i] == 0) q.push(i);
- }
-
- ve.assign(vertices, 0);
-
- while (!q.empty()) {
- int w = q.front();
- st_re.push(w);
- q.pop();
- for (int i = 0; i < vertices; i++) {
- if (adjMatrix[w][i] != 0) {
- init[i]--;
- if (init[i] == 0) q.push(i);
- if (ve[w] + adjMatrix[w][i] > ve[i]) ve[i] = ve[w] + adjMatrix[w][i];
- }
- }
- }
-
- // 输出每个顶点的最早开始时间
- for (int i = 0; i < vertices; i++) {
- cout << ve[i] << " ";
- }
- cout << endl;
-
- }
- void CriticalPath() {
- vl.assign(vertices, ve[st_re.top()]); // ***注意:vl的初始化是用拓扑排序的最后一个顶点的ve值做初始化,而非
- // 用ve[vertices - 1]做初始化,节点vertices - 1不一定为拓扑排序的最
- // 后一个顶点,即不一定为AOE网的终点
- while (!st_re.empty()) {
- int w = st_re.top();
- st_re.pop();
- for (int i = 0; i < vertices; i++) {
- if (adjMatrix[i][w] != 0) {
- if (vl[w] - adjMatrix[i][w] < vl[i]) vl[i] = vl[w] - adjMatrix[i][w];
- }
- }
- }
-
- // 输出每个顶点的最迟开始时间
- for (int i = 0; i < vertices; i++) {
- cout << vl[i] << " ";
- }
- cout << endl;
-
- // 输出关键路径
- for (int i = 0; i < vertices; i++) {
- if (i == vertices - 1) cout << i << endl;
- if (ve[i] == vl[i] && i < vertices - 1) cout << i << "->";
- }
- }
- };
-
- int main() {
- Graph G;
- G.build_Graph();
- G.Topoorder();
- G.CriticalPath();
- }
11、旅游规划
有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define INF 0x3f3f3f3f
- using namespace std;
-
-
- class Graph {
- int vertices;
- struct vec{
- int wag;
- int charge;
- };
- vector
> adjMatrix; - vector<int> vis;
- int start, end;
-
- public:
- Graph() {}
-
- void build_Graph() {
- int n;
- cin >> n;
- this->vertices = n;
- adjMatrix.assign(vertices, vector
(vertices, {0,0})); -
- int m;
- cin >> m;
-
- cin >> start >> end;
-
- for (int i = 0; i < m; i++) {
- int u, v, w, c;
- cin >> u >> v >> w >> c;
- addEdge(u, v, w, c);
- }
- }
-
- void addEdge(int from, int to, int w, int c) {
- adjMatrix[from][to].wag = w;
- adjMatrix[from][to].charge = c;
- }
-
- void Dijkstra() {
- vector<int> charge;
- charge.assign(vertices, 0);
- vis.assign(vertices, 0);
- vector<int> dis;
- dis.assign(vertices, INF);
-
- int v = start;
- vis[v] = 1;
- dis[v] = 0;
- charge[v] = 0;
-
- for (int i = 0; i < vertices; i++) {
- if(adjMatrix[v][i].wag)
- {
- dis[i] = dis[v] + adjMatrix[v][i].wag;
- charge[i] += adjMatrix[v][i].charge;
- }
- }
-
- for (int i = 0; i < vertices - 1; i++) {
- int Min = INF;
- for (int j = 0; j < vertices; j++)
- if (!vis[j] && Min > dis[j])
- {
- v = j;
- Min = dis[j];
- }
- vis[v] = 1;
-
- int tmpcharge;
- for (int j = 0; j < vertices; j++) {
- tmpcharge = INF;
- if (!vis[j] && adjMatrix[v][j].wag && Min + adjMatrix[v][j].wag <= dis[j]) {
- if (Min + adjMatrix[v][j].wag == dis[j] && charge[v] + adjMatrix[v][j].charge < tmpcharge) tmpcharge = charge[v] + adjMatrix[v][j].charge;
- dis[j] = Min + adjMatrix[v][j].wag;
- }
- if(tmpcharge != INF) charge[j] = tmpcharge;
- }
- }
- cout << dis[end] << " " << charge[end];
- }
- };
-
- int main() {
-
- Graph G;
- G.build_Graph();
- G.Dijkstra();
-
- }
12、拯救007(坐标转为图节点)
将坐标轴上的点看作图的节点,将岸上坐标、鳄鱼坐标和岛上中心看作节点,看能否从岛上中心的节点遍历到岸上节点,若可,即可以逃脱
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define INF 0x3f3f3f3f
- using namespace std;
-
-
- class Graph {
- int vertices;
- vector
int>> adjMatrix; - struct Node {
- int x, y;
- Node() {}
- Node(int xx, int yy) { x = xx, y = yy; }
- };
- vector<int> vis;
- int D;
- vector
node; - int flag;
-
- public:
- Graph() {}
-
- void build_Graph() {
- int n;
- cin >> n;
- this->vertices = n + 1;
- adjMatrix.assign(vertices + 1, vector<int>(vertices + 1, 0));
- cin >> D;
-
- for (int i = 0; i < n; i++) {
- int x, y;
- cin >> x >> y;
- node.push_back(Node{ x,y });
- }
- node.push_back(Node{ 0,0 });
-
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++) {
- if (i == j || distance(node[i], node[j]) > D) adjMatrix[i][j] = 0;
- else if (distance(node[i], node[j]) <= D) {
- adjMatrix[i][j] = 1;
- adjMatrix[j][i] = 1;
- }
- }
- }
- for (int i = 0; i < n; i++) {
- if (node[i].x*node[i].x + node[i].y * node[i].y <= (7.5 + D)*(7.5 + D)) {
- adjMatrix[n][i] = 1;
- }
- else {
- adjMatrix[n][i] = 0;
- }
- }
- adjMatrix[n][n] = 0;
- }
-
- double distance(Node a, Node b) {
- return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
- }
-
- void addEdge(int from, int to, int value) {
- adjMatrix[from][to] = value;
- }
- int check(Node p) {
- if (p.x - (-50) <= D || 50 - p.x <= D || p.y - (-50) <= D || 50 - p.y <= D) {
- return 1;
- }
- else return 0;
- }
-
-
- int DFS() {
-
- vis.assign(vertices, 0);
- flag = 0;
-
-
- for (int i = 0; i < vertices - 1; i++)
- {
- if (!vis[i] && adjMatrix[vertices - 1][i]) // 遍历图的起点只能从(0,0)开始
- {
-
- DFSRecursive(i);
- }
- if (flag == 1) return 1;
- }
- return 0;
- }
-
- void DFSRecursive(int vertex) {
- vis[vertex] = 1;
- if (check(node[vertex]) || flag == 1)
- {
- flag = 1; return;
- }
- for (int i = 0; i < vertices - 1; i++)
- {
- if (!vis[i] && adjMatrix[vertex][i])
- {
- DFSRecursive(i);
- }
- }
-
- }
- };
-
- int main() {
- Graph G;
- G.build_Graph();
- int check = G.DFS();
- if (check == 1) {
-
- printf("Yes\n");
- }
- else {
- printf("No\n");
- }
- }
13、判断环
无向图:将图中度为1的顶点一个个删掉,同时把与该顶点相连的顶点度数减1,若图中仍存在度大于1的顶点,说明图中有环。
有向图:将图中入度为0的顶点一个个删掉,同时把与该顶点相连的顶点入度减1,若图中仍存在入读不为0的顶点,说明图中有环。
- // 无向图判断环
-
- #include
- #define MAXN 100010
- using namespace std;
-
- vector
int>> vec; - int n;
- vector<int> d;
-
- int main()
- {
- cin >> n;
- d.resize(n + 1, 0);
- vec.resize(n + 1);
- for (int i = 1; i <= n; i++) {
- int a, b;
- cin >> a >> b;
- d[a]++, d[b]++;
- vec[a].push_back(b);
- vec[b].push_back(a);
- }
-
- queue<int> q;
- for (int i = 1; i <= n; i++) {
- if (d[i] == 1) q.push(i);
- }
- while (!q.empty()) {
- int p = q.front();
- q.pop();
- for (int i = 0; i < vec[p].size(); i++) {
- --d[vec[p][i]];
- if (d[vec[p][i]] == 1) {
- q.push(vec[p][i]);
- }
- }
- }
- for (int i = 1; i <= n; i++) {
- if (d[i] > 1) cout << i << " ";
- }
- return 0;
- }