实验5-图

报告内容

实验目标:

  1. 学会创建图(邻接矩阵),掌握在图上的基本操作。
  2. 掌握图遍历算法:DFS与BFS。
  3. 掌握编写最小生成树算法。

实验内容:

  1. 任务书:题目1—图的创建
  2. 任务书:题目2—图的遍历(DFS、BFS)
  3. PTA:图着色问题
  4. 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:图的创建

本机运行截图
image

题目2:图的遍历

本机运行截图
image
image
image
image
image

题目3:图着色问题

本机运行截图
image
image
image

题目4:公路村村通(最小生成树)

本机运行截图
image
image
image
image
image
image
image
image
image

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

posted @ 2026-06-07 14:20  lansariel  阅读(31)  评论(0)    收藏  举报