1、邻接矩阵(vector二维数组)的DFS(递归实现)
class Graph {
public:
Graph(int vertices);
void addEdge(int from, int to);
void DFS(int startVertex);
private:
int vertices;
vector<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<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<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 <iostream>
#include <vector>
#include <queue>
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、最小生成树
连通的带权无向图称为连通网。
最小生成树(Minimum Cost Spanning Tree)是代价最小的连通网的生成树,即该生成树上的边的权值和最小。
最小生成树的性质:
必须使用且仅使用连通网中的n-1条边来联结网络中的n个顶点;
不能使用产生回路的边;
各边上的权值的总和达到最小。
(1)Prim算法
class Graph {
int vertices;
vector<vector<int>> adjMatrix;
map<string, 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<Closeedge> 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> 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<vector<int>> adjMatrix;
map<string, 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<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<edge> ans; // 记录最小生成树上的每条路径
vector<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 <iostream>
#include <vector>
#include <stack>
using namespace std;
// 树节点
struct treenode{
int val;
vector<treenode*> son; // 存儿子节点指针
treenode(int n) { val = n; }
};
vector<treenode*> Root; // 存每棵树的树根
class Graph {
public:
Graph(int vertices);
void addEdge(int from, int to);
void DFS();
treenode* DFSRecursive(int vertex);
private:
int vertices;
vector<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<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
class Graph {
int vertices;
vector<vector<int>> adjMatrix;
map<string, 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<queue<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<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
class Graph {
int vertices;
vector<vector<double>> adjMatrix;
map<string, int> ele1;
map<int, string> ele2;
vector<int> vis;
vector<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<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
class Graph {
int vertices;
vector<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<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
class Graph {
int vertices;
struct vec{
int wag;
int charge;
};
vector<vector<vec>> adjMatrix;
vector<int> vis;
int start, end;
public:
Graph() {}
void build_Graph() {
int n;
cin >> n;
this->vertices = n;
adjMatrix.assign(vertices, vector<vec>(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<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
class Graph {
int vertices;
vector<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> 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<bits/stdc++.h>
#define MAXN 100010
using namespace std;
vector<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;
}