shiyan5
集美大学课程实验报告-实验5:图
| 项目名称 | 内容 |
|---|---|
| 课程名称 | 数据结构 |
| 实验项目名称 | 图 |
| 上机实践日期 | 2026年6月6日 |
| 上机实践时间 | 2小时 |
一、目的
- 掌握创建图的代码
- 熟悉BFS和DFS遍历的使用
- 学会运用图来解决实际问题
二、实验内容与设计思想
题目1和2:图的创建以及遍历
函数相关伪代码
1.Graph{
整数 vertexCount
整数 edgeCount
二维数组 adjMatrix
私有辅助函数:
函数 DFSUtil(整数 v, 布尔数组引用 visited):
visited[v] = true
输出 v
对于 i 从 0 到 vertexCount-1:
如果 adjMatrix[v][i] != 0 且 visited[i] == false:
调用 DFSUtil(i, visited)
公共部分:
构造Graph函数
添加addEdge
函数 DFS(整数 start):
如果 start 无效: 提示并返回
创建布尔数组 visited[vertexCount],初始全 false
输出 "DFS 遍历结果:"
调用 DFSUtil(start, visited)
对于 i 从 0 到 vertexCount-1:
如果 visited[i] == false:
调用 DFSUtil(i, visited)
函数 BFS(整数 start):
如果 start 无效: 提示并返回
创建布尔数组 visited[vertexCount],初始全 false
创建队列 q
visited[start] = true
q.push(start)
输出 "BFS 遍历结果:"
当 q 非空:
v = q.front(); q.pop()
输出 v
对于 i 从 0 到 vertexCount-1:
如果 adjMatrix[v][i] != 0 且 visited[i] == false:
visited[i] = true
q.push(i)
对于 i 从 0 到 vertexCount-1:
如果 visited[i] == false:
visited[i] = true
q.push(i)
当 q 非空:
v = q.front(); q.pop()
输出 v
对于 j 从 0 到 vertexCount-1:
如果 adjMatrix[v][j] != 0 且 visited[j] == false:
visited[j] = true
q.push(j)
}
2.主函数
先构造Graph
再进行BFS和DFS进行遍历
函数代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
class Graph
{
private:
int vertexCount;
int edgeCount;
vector<vector<int>>adjMatrix;
void DFSUtil(int v, vector<bool>& visited)
{
visited[v] = true;
cout << v << " ";
for (int i = 0; i < vertexCount; i++)
{
if (adjMatrix[v][i] != 0 && !visited[i])
{
DFSUtil(i, visited);
}
}
}
public:
Graph(int v) :vertexCount(v), edgeCount(0)
{
adjMatrix.resize(v, vector<int>(v, 0));
}
void addEdge(int u, int v, int weight = 1)
{
if (u < 0 || u >= vertexCount || v < 0 || v >= vertexCount)return;
if (adjMatrix[u][v] == 0)
{
adjMatrix[u][v] = weight;
adjMatrix[v][u] = weight;
edgeCount++;
}
}
void DFS(int start)
{
if (start < 0 || start >= vertexCount)
{
cout << "起始顶点无效!" << endl;
return;
}
vector<bool>visited(vertexCount, false);
cout << "DFS遍历结果(从顶点 " << start << "开始):";
DFSUtil(start, visited);
for (int i = 0; i < vertexCount;i++)
{
if (!visited[i])
{
DFSUtil(i, visited);
}
}
cout << endl;
}
void BFS(int start)
{
if (start < 0 || start >= vertexCount)
{
cout << "起始顶点无效!" << endl;
return;
}
vector<bool>visited(vertexCount, false);
queue<int>q;
visited[start] = true;
q.push(start);
cout << "BFS遍历结果(从顶点 " << start << "开始) :";
while (!q.empty())
{
int v = q.front(); q.pop();
cout << v << " ";
for (int i = 0; i < vertexCount; i++)
{
if (adjMatrix[v][i] != 0 && !visited[i])
{
visited[i] = true;
q.push(i);
}
}
}
for (int i = 0; i < vertexCount; i++)
{
if (!visited[i])
{
visited[i] = true;
q.push(i);
while (!q.empty())
{
int v = q.front(); q.pop();
cout << v << " ";
for (int j = 0; j < vertexCount; j++)
{
if (adjMatrix[v][j] != 0 && !visited[j])
{
visited[j] = true;
q.push(j);
}
}
}
}
}
cout << endl;
}
void printMatrix()
{
cout << "邻接矩阵:" << endl;
for (int i = 0; i < vertexCount; i++)
{
for (int j = 0; j < vertexCount; j++)
{
cout << adjMatrix[i][j] << "\t";
}
cout << endl;
}
}
void printInfo()
{
cout << "顶点数:" << vertexCount << endl;
cout << "边数:" << edgeCount << endl;
}
};
int main()
{
Graph g(4);
g.addEdge(0, 1, 5);
g.addEdge(0, 2, 3);
g.addEdge(1, 3, 2);
g.addEdge(2, 3, 4);
g.addEdge(1, 2, 6);
g.printInfo();
g.printMatrix();
g.DFS(0);
g.BFS(0);
return 0;
}
题目3:图着色问题
函数相关伪代码
1.输入V,E,K
2.构造两个数组,分别存放一个边的两个邻结点
3.while(N--)
{
整数 color[501];
整数 used[501]={0};
整数 colorCount=0;
for(整数 i=1;i<=V;i++)
{
输入color[i];
if(used[color[i]]==0)
{
used[color[i]]=1;
colorCount++;
}
}
if(colorCount!=K)
{
输出"No"
continue;
}
bool ok=true;
for(整数 i=0;i<E;i++)
{
if(color[u[i]]==color[v[i]])
{
ok=false;
break;
}
}
if ok为真,输出Yes,否则输出No
}
函数代码
#include<iostream>
using namespace std;
int main()
{
int V,E,K;
cin>>V>>E>>K;
int u[500000],v[500000];
for(int i=0;i<E;i++)
{
cin>>u[i]>>v[i];
}
int N;
cin>>N;
while(N--)
{
int color[501];
int used[501]={0};
int colorCount=0;
for(int i=1;i<=V;i++)
{
cin>>color[i];
if(used[color[i]]==0)
{
used[color[i]]=1;
colorCount++;
}
}
if(colorCount!=K)
{
cout<<"No"<<endl;
continue;
}
bool ok=true;
for(int i=0;i<E;i++)
{
if(color[u[i]]==color[v[i]])
{
ok=false;
break;
}
}
cout<<(ok?"Yes":"No")<<endl;
}
return 0;
}
题目4:公路村村通(最小生成树)
函数相关伪代码
1. 将 edges 按 cost 从小到大排序
2. 初始化并查集 parent[1..n],每个节点的父节点初始化为自身
3. 初始化 total_cost = 0,selected_edges = 0
4. 对于 edges 中的每条边 (u, v, cost) 按升序执行:
root_u = Find(u)
root_v = Find(v)
如果 root_u ≠ root_v:
parent[root_u] = root_v // 合并两个集合
total_cost = total_cost + cost
selected_edges = selected_edges + 1
如果 selected_edges == n-1:
跳出循环
5. 如果 selected_edges == n-1:
输出 total_cost
否则:
输出 -1
子函数 Find(x):
如果 parent[x] ≠ x:
parent[x] = Find(parent[x]) // 路径压缩
返回 parent[x]
函数代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Edge {
int u, v, cost;
};
vector<int> parent;
int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
}
bool unite(int a, int b) {
int ra = find(a), rb = find(b);
if (ra == rb) return false;
parent[ra] = rb;
return true;
}
int main() {
int n, m;
cin >> n >> m;
vector<Edge> edges(m);
for (int i = 0; i < m; ++i) {
cin >> edges[i].u >> edges[i].v >> edges[i].cost;
}
sort(edges.begin(), edges.end(), [](const Edge &a, const Edge &b) {
return a.cost < b.cost;
});
parent.resize(n + 1);
for (int i = 1; i <= n; ++i) parent[i] = i;
int total_cost = 0;
int selected_edges = 0;
for (const auto &e : edges) {
if (unite(e.u, e.v)) {
total_cost += e.cost;
selected_edges++;
if (selected_edges == n - 1) break;
}
}
if (selected_edges == n - 1)
cout << total_cost << endl;
else
cout << -1 << endl;
return 0;
}
三、实验使用环境
- 操作系统:Windows11 专业版
- 编程语言:C++
- 开发工具:visual studio
四、实验步骤和调试过程
题目1和2:图的构建和遍历
本机运行截图

题目3:图着色问题
PTA提交截图

题目4:公路村村通(最小生成树)
PTA提交截图
![image]()
与AI对话
![image]()
![image]()
![image]()
![image]()
五、实验小结
遇到的问题及解决方法:
1.问题:BFS的代码不太会表示
- 解决方法:询问ai,看懂每一步并和自己所学的知识对照
实验体会与收获:
- 学会了构建图,并且进行两种方法进行遍历
- 掌握了运用图来解决实际问题
六、附件
无






浙公网安备 33010602011771号