西南交通大学离散数学第四次大作业

省流

四个大作业中唯一一个用gpt写的,实在是懒癌犯了,见谅见谅。。。。

图着色算法的实现说明

1. 概述

本文档详细介绍了如何基于韦尔奇-鲍威尔(Welch-Powell)算法对无向图进行顶点着色,并将结果存储到文件中。我们使用C++语言实现该算法,通过合理的数据结构和面向对象编程思想,确保算法的高效性和可读性。

2. 存储结构

为了实现图的表示和操作,我们定义了一个结构体 Graph。该结构体包含以下成员:

  • int V: 图的顶点数。
  • vector<vector<int>> adj: 邻接表,用于存储每个顶点的邻接顶点。

3. 主要算法

3.1 图的初始化和边的添加

通过 Graph 结构体的构造函数初始化图的顶点数,并通过 addEdge 函数向图中添加边,更新邻接表。

cpp

struct Graph {
    int V;
    vector<vector<int>> adj;

    Graph(int V) : V(V), adj(V) {}

    void addEdge(int v, int w) {
        adj[v].push_back(w);
        adj[w].push_back(v);
    }

    vector<int> getDegrees() const {
        vector<int> degrees(V, 0);
        for (int v = 0; v < V; ++v) {
            degrees[v] = adj[v].size();
        }
        return degrees;
    }
};
3.2 节点的度数降序排序

我们定义 sortVerticesByDegree 函数,根据节点的度数对顶点进行降序排序。

cpp

vector<int> sortVerticesByDegree(const Graph& graph) {
    vector<int> vertices(graph.V);
    vector<int> degrees = graph.getDegrees();
    for (int i = 0; i < graph.V; ++i) {
        vertices[i] = i;
    }
    sort(vertices.begin(), vertices.end(), [&degrees](int a, int b) {
        return degrees[a] > degrees[b];
    });
    return vertices;
}
3.3 韦尔奇-鲍威尔算法实现图着色

welshPowellColoring 函数中实现韦尔奇-鲍威尔算法。算法步骤如下:

  1. 获取按度数降序排序的顶点列表。
  2. 初始化一个颜色数组,所有顶点初始时未着色(用 -1 表示)。
  3. 按排序后的顺序遍历每个顶点,给未着色的顶点分配一个新的颜色。
  4. 着色所有与当前顶点无直接边的顶点,确保相邻顶点不同色。
 

cpp

void welshPowellColoring(const Graph& graph) {
    vector<int> sortedVertices = sortVerticesByDegree(graph);
    vector<int> colors(graph.V, -1);
    int color = 0;

    for (int vertex : sortedVertices) {
        if (colors[vertex] == -1) {
            colors[vertex] = ++color;
            for (int neighbor : sortedVertices) {
                if (colors[neighbor] == -1) {
                    bool canColor = true;
                    for (int adj : graph.adj[neighbor]) {
                        if (colors[adj] == color) {
                            canColor = false;
                            break;
                        }
                    }
                    if (canColor) {
                        colors[neighbor] = color;
                    }
                }
            }
        }
    }

    for (int i = 0; i < graph.V; ++i) {
        cout << "v" << i + 1 << ":" << colors[i] << (i == graph.V - 1 ? "" : ",");
    }
    cout << endl;

    ofstream file("graph.txt");
    if (file.is_open()) {
        for (int i = 0; i < graph.V; ++i) {
            file << "v" << i + 1 << ":" << colors[i] << (i == graph.V - 1 ? "" : ",");
        }
        file << endl;
        file.close();
        cout << "结果已正确存入文件graph.txt." << endl;
    } else {
        cerr << "文件存储失败" << endl;
    }
}

4. 输入与输出的实现

输入

程序从控制台输入图的顶点数和边信息。

输出

程序首先将着色结果输出到控制台,然后将结果存入文件 graph.txt 中。

cpp
int main() {
    int V = 5;
    Graph graph(V);

    graph.addEdge(0, 1);
    graph.addEdge(0, 2);
    graph.addEdge(1, 2);
    graph.addEdge(1, 3);
    graph.addEdge(2, 4);

    welshPowellColoring(graph);

    return 0;
}

5. 面向对象编程设计

类的设计

Graph 结构体包含图的基本信息和操作方法:

  • V: 顶点数。
  • adj: 邻接表。
  • addEdge: 添加边。
  • getDegrees: 计算每个顶点的度数。

通过函数实现图的操作,如节点排序和图着色。此设计遵循面向对象编程的原则,将图的结构和操作封装在一起,便于代码的维护和扩展。

6. 总结

本文介绍了如何使用韦尔奇-鲍威尔算法对图进行顶点着色,并将结果存储到文件中。通过合理的数据结构和算法设计,程序能够高效地处理图的着色问题,并且具有良好的可扩展性和可维护性。

代码

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream> // 引入文件流库
using namespace std;

// 定义一个图的结构
struct Graph {
    int V;                                            // 图的顶点数
    vector<vector<int>> adj;                          // 邻接表

    // 构造函数
    Graph(int V) : V(V), adj(V) {}

    // 添加边
    void addEdge(int v, int w) {
        adj[v].push_back(w);
        adj[w].push_back(v);
    }

    // 计算每个顶点的度数
    vector<int> getDegrees() const {
        vector<int> degrees(V, 0);
        for (int v = 0; v < V; ++v) {
            degrees[v] = adj[v].size();
        }
        return degrees;
    }
};

// 根据节点的度数降序排序
vector<int> sortVerticesByDegree(const Graph& graph) {
    vector<int> vertices(graph.V);
    vector<int> degrees = graph.getDegrees();
    for (int i = 0; i < graph.V; ++i) {
        vertices[i] = i;
    }
    sort(vertices.begin(), vertices.end(), [&degrees](int a, int b) {
        return degrees[a] > degrees[b];
        });
    return vertices;
}

// 实现韦尔奇·鲍威尔算法进行图着色
void welshPowellColoring(const Graph& graph) {
    vector<int> sortedVertices = sortVerticesByDegree(graph);
    vector<int> colors(graph.V, -1); // 用-1表示未着色
    int color = 0;

    // 遍历每一个顶点,按照降序顺序进行着色
    for (int vertex : sortedVertices) {
        if (colors[vertex] == -1) { // 如果顶点尚未着色
            colors[vertex] = ++color; // 使用新颜色
            // 着色所有与当前顶点无直接边的顶点
            for (int neighbor : sortedVertices) {
                if (colors[neighbor] == -1) { // 如果邻接顶点尚未着色
                    bool canColor = true;
                    for (int adj : graph.adj[neighbor]) {
                        if (colors[adj] == color) { // 如果相邻顶点颜色相同
                            canColor = false;
                            break;
                        }
                    }
                    if (canColor) {
                        colors[neighbor] = color; // 着色
                    }
                }
            }
        }
    }

    // 输出着色结果到控制台
    for (int i = 0; i < graph.V; ++i) {
        cout << "v" << i + 1 << ":" << colors[i] << (i == graph.V - 1 ? "" : ",");
    }
    cout << endl;

    // 将着色结果写入文件graph.txt
    ofstream file("graph.txt");
    if (file.is_open()) {
        for (int i = 0; i < graph.V; ++i) {
            file << "v" << i + 1 << ":" << colors[i] << (i == graph.V - 1 ? "" : ",");
        }
        file << endl;
        file.close();
        cout << "正确存入文件graph.txt." << endl;
    }
    else {
        cerr << "存入失败" << endl;
    }
}

int main() {
    // 定义图的节点数和边
    int V = 5; // 例如有5个节点
    Graph graph(V);

    // 添加图的边
    graph.addEdge(0, 1);
    graph.addEdge(0, 2);
    graph.addEdge(1, 2);
    graph.addEdge(1, 3);
    graph.addEdge(1, 4);
    graph.addEdge(2, 4);
    graph.addEdge(3, 4);

    // 使用韦尔奇·鲍威尔算法对图进行着色并输出结果
    welshPowellColoring(graph);

    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值