实验5-图
报告内容
实验目标:
- 学会创建图(邻接矩阵),掌握在图上的基本操作。
- 掌握图遍历算法:DFS与BFS。
- 掌握编写最小生成树算法。
实验内容:
- 任务书:题目1—图的创建
- 任务书:题目2—图的遍历(DFS、BFS)
- PTA:图着色问题
- AI任务:公路村村通(最小生成树)
实验报告编写
一、目的
1.学会图的创建,邻接矩阵
2.学会用DFS和BFS遍历
3.最小生成树
二、实验内容与设计思想
题目1:图的创建
1.内容:给出图的存储结构,编写创建图的伪代码。初始化图:初始化点数、边数;初始化点列表;初始化边矩阵
函数相关伪代码
#define MAXVEXNUM 100
typedef int ArcCell;
typedef char VexType;
typedef struct {
VexType vexs[MAXVEXNUM]; //点集
ArcCell arcs[MAXVEXNUM][MAXVEXNUM]; // 边集
int vexNum, arcNum; //点数,边数
}MyGraph;
函数代码
#include <stdio.h>
#include <string.h>
#define MAXVEXNUM 100
typedef int ArcCell;
typedef char VexType;
typedef struct {
VexType vexs[MAXVEXNUM];
ArcCell arcs[MAXVEXNUM][MAXVEXNUM];
int vexNum, arcNum;
} MyGraph;
MyGraph G;
int LocateVex(MyGraph G, VexType v) {
for (int i = 0; i < G.vexNum; i++) {
if (G.vexs[i] == v) return i;
}
return -1;
}
void CreateMGraph() {
scanf_s("%d %d", &G.vexNum, &G.arcNum);
for (int i = 0; i < G.vexNum; i++) {
scanf_s(" %c", &G.vexs[i], 1);
}
memset(G.arcs, 0, sizeof(G.arcs));
for (int k = 0; k < G.arcNum; k++) {
char v1, v2;
scanf_s(" %c %c", &v1, 1, &v2, 1);
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
G.arcs[i][j] = 1;
G.arcs[j][i] = 1;
}
}
void PrintMGraph() {
for (int i = 0; i < G.vexNum; i++) {
for (int j = 0; j < G.vexNum; j++) {
printf("%d ", G.arcs[i][j]);
}
printf("\n");
}
}
int main() {
CreateMGraph();
PrintMGraph();
return 0;
}
题目2:图的遍历
函数相关伪代码
DFS(v):
visited[v] = true
visit(vexs[v])
for j = 0 to n-1:
if arcs[v][j] == 1 and not visited[j]:
DFS(j)
BFS(v):
创建空队列 Q
visited[v] = true
visit(vexs[v])
Q.enqueue(v)
while Q not empty:
cur = Q.dequeue()
for j = 0 to n-1:
if arcs[cur][j] == 1 and not visited[j]:
visited[j] = true
visit(vexs[j])
Q.enqueue(j)
函数代码
#include <stdio.h>
#include <string.h>
#define MAXVEXNUM 100
typedef int ArcCell;
typedef char VexType;
typedef struct {
VexType vexs[MAXVEXNUM];
ArcCell arcs[MAXVEXNUM][MAXVEXNUM];
int vexNum, arcNum;
} MyGraph;
MyGraph G;
int visited[MAXVEXNUM];
int LocateVex(MyGraph G, VexType v) {
for (int i = 0; i < G.vexNum; i++) {
if (G.vexs[i] == v) return i;
}
return -1;
}
void CreateMGraph() {
scanf_s("%d %d", &G.vexNum, &G.arcNum);
for (int i = 0; i < G.vexNum; i++) {
scanf_s(" %c", &G.vexs[i], 1);
}
memset(G.arcs, 0, sizeof(G.arcs));
for (int k = 0; k < G.arcNum; k++) {
char v1, v2;
scanf_s(" %c %c", &v1, 1, &v2, 1);
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
G.arcs[i][j] = 1;
G.arcs[j][i] = 1;
}
}
void PrintMGraph() {
for (int i = 0; i < G.vexNum; i++) {
for (int j = 0; j < G.vexNum; j++) {
printf("%d ", G.arcs[i][j]);
}
printf("\n");
}
}
void DFS(int v) {
visited[v] = 1;
printf("%c ", G.vexs[v]);
for (int j = 0; j < G.vexNum; j++) {
if (G.arcs[v][j] == 1 && !visited[j]) {
DFS(j);
}
}
}
void DFSTraverse() {
memset(visited, 0, sizeof(visited));
for (int i = 0; i < G.vexNum; i++) {
if (!visited[i]) {
DFS(i);
}
}
printf("\n");
}
void BFS(int v) {
int queue[MAXVEXNUM];
int front = 0, rear = 0;
visited[v] = 1;
printf("%c ", G.vexs[v]);
queue[rear++] = v;
while (front != rear) {
int cur = queue[front++];
for (int j = 0; j < G.vexNum; j++) {
if (G.arcs[cur][j] == 1 && !visited[j]) {
visited[j] = 1;
printf("%c ", G.vexs[j]);
queue[rear++] = j;
}
}
}
}
void BFSTraverse() {
memset(visited, 0, sizeof(visited));
for (int i = 0; i < G.vexNum; i++) {
if (!visited[i]) {
BFS(i);
}
}
printf("\n");
}
int main() {
CreateMGraph();
PrintMGraph();
printf("DFS: ");
DFSTraverse();
printf("BFS: ");
BFSTraverse();
return 0;
}
题目3:图着色问题
函数相关伪代码
输入:顶点数 n,边数 m,边列表,每个顶点的颜色列表
输出:是否为合法 3-着色(使用颜色 1,2,3 且相邻点不同色)
读取 n, m。创建邻接表,读取 m 条边并插入邻接表,读取测试方案数
对于每个测试方案:读取 n 个顶点的颜色, 调用 checkColoring 输出 YES/NO
释放动态内存
函数代码
#include <stdio.h>
#include <string.h>
int main() {
int V, E, K;
scanf("%d %d %d", &V, &E, &K);
int edges[100][2];
for (int i = 0; i < E; i++) {
scanf("%d %d", &edges[i][0], &edges[i][1]);
}
int N;
scanf("%d", &N);
while (N--) {
int color[501];
int used[501] = {0};
int colorCnt = 0;
for (int i = 1; i <= V; i++) {
scanf("%d", &color[i]);
if (!used[color[i]]) {
used[color[i]] = 1;
colorCnt++;
}
}
if (colorCnt != K) {
printf("No\n");
continue;
}
int ok = 1;
for (int i = 0; i < E; i++) {
int u = edges[i][0], v = edges[i][1];
if (color[u] == color[v]) {
ok = 0;
break;
}
}
printf("%s\n", ok ? "Yes" : "No");
}
return 0;
}
题目4:公路村村通(最小二叉树)
函数相关伪代码
##目标
帮我检查如下使用Prim算法解决公路村村通问题的思路是否正确
##解题步骤如下
###定义图的数据结构
使用邻接矩阵作为图的存储结构
#define Max_Vex 100
typedef struct{
vexs[Max_Vex]; //点列表
edges[Max_Vex][Max_Vex]; //代表边的矩阵
}Mygraph
###2.我的最小生成树算法伪代码或思路
起始点visited[0]=true;
初始化数组lowcost: lowcost[i]设为起点到各个村子的距离(edges[0][i])
int n; //村子总数
for(n-1)循环找到与初始点邻接点
for循环找到与初始点边数最小的那个邻接点k,加入树
将k作为新的起始点visited[k]=true;
遍历剩下未被访问过的点 j visited[j]=false;
if(edges[k][j]<lowcost[j]){
lowcost[j]=edges[k][j]
}
函数代码
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define Max_Vex 1001 // 题目中 N <= 1000,稍微开大一点防止越界
#define INF 0x3f3f3f3f // 定义一个极大值,代表无穷大(不可达)
typedef struct {
int edges[Max_Vex][Max_Vex]; // 邻接矩阵
int n, m; // n为顶点数,m为边数
} Mygraph;
Mygraph G;
int lowcost[Max_Vex];
bool visited[Max_Vex];
// 初始化图
void initGraph() {
// 注意:PTA这道题的输入格式是先输入N(村子数),再输入M(道路数)
cin >> G.n >> G.m;
// 初始化邻接矩阵
for (int i = 1; i <= G.n; i++) {
for (int j = 1; j <= G.n; j++) {
if (i == j) G.edges[i][j] = 0;
else G.edges[i][j] = INF;
}
}
// 读入边
for (int i = 0; i < G.m; i++) {
int u, v, w;
cin >> u >> v >> w;
// 无向图,且可能存在重边,取最小权值
G.edges[u][v] = min(G.edges[u][v], w);
G.edges[v][u] = min(G.edges[v][u], w);
}
}
int prim() {
int totalCost = 0; // 记录最小生成树的总成本
// 1. 初始化:从 1 号点开始
memset(visited, false, sizeof(visited));
for (int i = 1; i <= G.n; i++) {
lowcost[i] = G.edges[1][i]; // 初始化为起点到各个村子的距离
}
visited[1] = true;
lowcost[1] = 0;
// 2. 循环 n-1 次,寻找剩下的 n-1 个节点
for (int i = 1; i < G.n; i++) {
int minDist = INF;
int k = -1; // 记录找到的最小边对应的顶点
// 遍历所有未访问的点,找到距离当前生成树最近的点 k
for (int j = 1; j <= G.n; j++) {
if (!visited[j] && lowcost[j] < minDist) {
minDist = lowcost[j];
k = j;
}
}
// 如果找不到有效点(minDist 仍为 INF),说明图不连通
if (k == -1) return -1;
// 将 k 加入树
visited[k] = true;
totalCost += minDist;
// 3. 更新 lowcost 数组
for (int j = 1; j <= G.n; j++) {
if (!visited[j] && G.edges[k][j] < lowcost[j]) {
lowcost[j] = G.edges[k][j];
}
}
}
return totalCost;
}
int main() {
// 优化 I/O 效率,防止在 PTA 上因为输入输出慢而超时
ios::sync_with_stdio(false);
cin.tie(0);
initGraph();
int result = prim();
cout << result << endl;
return 0;
}
三. 实验使用环境
Windows111
Visual Studio 2026
四. 实验结果
题目1:图的创建
本机运行截图

题目2:图的遍历
本机运行截图





题目3:图着色问题
本机运行截图



题目4:公路村村通(最小生成树)
本机运行截图









五、实验小结
问题:1.开始我使用 C++ 语法,但评测环境指定为 gcc c11,导致编译失败。通过将代码改写为标准 C 语言解决了该问题。
问题:2遇到了栈溢出的问题。改成非递归的方法

浙公网安备 33010602011771号