图论---无向图中国邮路的实现

开始编程前分析设计思路和程序的整体的框架,以及作为数学问题的性质:

程序流程图:

数学原理:

本质上是找到一条欧拉回路,考虑图中的边权重、顶点的度数以及如何通过添加最少的额外边来构造欧拉回路,涉及到欧拉回路、最短路径算法以及奇点匹配。

时间复杂度分析:

程序的时间复杂度主要来自于Floyd算法和ADD函数。Floyd是动态规划算法。它的时间复杂度是O(n^3)。 ADD函数是一个递归函数它的时间复杂度是O(2^n),其中n是奇点的数量。在最坏情况下,奇点的数量可能接近于节点的数量,ADD函数的时间复杂度可能接近于O(2^n)。综合看,这段程序的时间复杂度是O(n^3 + 2^n)。由于2^n的增长速度非常快,当n较大时,2^n将远大于n^3,因此这段程序的时间复杂度应该为O(2^n)

源代码:

cpp 复制代码
#include <stdio.h>
#include <bits.h>
// 定义常量
const int N = 105;
const int inf = 100000000;
// 建立矩阵和路径数组
int matrix[N][N], mapp[N][N];
int p[N][N];
int path[N], d[N];
int sg[N];
int cont[N];
int vis[N];
int n, m;
int top;
// 设置结构体将边和权重关联
struct node
{
    int v, u, cost;
} gg[N];
// 使用深度优先递归搜索
void DFS(int beg)
{
    for (int i = 1; i <= n; i++)
    {
        if (matrix[beg][i])
        {
            matrix[beg][i]--;
            matrix[i][beg]--;
            DFS(i);
        }
    }
    path[top++] = beg;
}
void Fleury(int beg)
{
    top = 0;
    DFS(beg);
}
// 寻找最短路径
void Floyed()
{
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            for (int k = 1; k <= n; k++)
            {
                if (mapp[i][j] > mapp[i][k] + mapp[k][j])
                {
                    p[i][j] = k;
                    mapp[i][j] = mapp[i][k] + mapp[k][j];
                }
            }
        }
    }
}
// 通过递归对奇数边进行加边
int ADD(int cn)
{ // 将奇点进行匹配得一个最小的
    int ans = inf;
    if (cn < 2)
        return 0; // 奇点个数小于2,无需匹配。
    for (int i = 1; i <= cn; i++)
    {
        if (sg[i] != 0)
        {
            for (int j = i + 1; j <= cn; j++)
            {
                if (sg[j] != 0)
                {
                    int tem1 = sg[i], tem2 = sg[j];
                    sg[i] = 0;
                    sg[j] = 0;
                    if (ans > ADD(cn - 2) +mapp[tem1][tem2])
                    {
// 第i个奇点匹配的奇点是第j个奇点
                        cont[i] = tem2; 
// 第j个奇点匹配的奇点是第i个奇点
                        cont[j] = tem1; 
                        ans = ADD(cn - 2)+mapp[tem1][tem2];
                    }
                    sg[i] = tem1;
                    sg[j] = tem2;
                }
            }
        }
    }
    return ans;
}
// 将找到的路径存储
void AddPath(int cn)
{
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= cn; i++)
    {
        if (!vis[sg[i]])
        {
            vis[sg[i]] = 1;
            vis[cont[i]] = 1;
            while (p[sg[i]][cont[i]])
            {
                int sss = cont[i];
                cont[i] = p[sg[i]][cont[i]];
                matrix[sss][cont[i]]++;
                matrix[cont[i]][sss]++;
            }
            matrix[sg[i]][cont[i]]++;
            matrix[cont[i]][sg[i]]++;
        }
    }
}
// 输出路径
void Print_Path()
{
    printf("top=%d\n", top);
    for (int i = top - 1; i >= 0; i--)
    {
        printf("%d", path[i]);
        if (i)
            printf("->");
    }
    puts("");
}
//初始化各边信息
void Inif()
{
    for (int i = 0; i <= N; i++)
    {
        for (int j = 0; j <= N; j++)
        {
            mapp[i][j] = (i == j) ? 0 : inf;
        }
    }
}
// 中国邮路信息建立
void CNLoad()
{
    while (~scanf("%d%d", &n, &m))
    {
        Inif();
        int i, beg, sum = 0; // sum用来计算路径长度
        memset(matrix, 0, sizeof(matrix));
        memset(d, 0, sizeof(d));
        memset(sg, 0, sizeof(sg));
        memset(path, 0, sizeof(path));
        memset(p, 0, sizeof(p));
        memset(cont, 0, sizeof(cont));
        // 存储各边信息
        for (i = 1; i <= m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            d[a]++;
            d[b]++;
            matrix[a][b] = 1;
            matrix[b][a] = 1;
            mapp[a][b] = c;
            mapp[b][a] = c;
            gg[i].v = a;
            gg[i].u = b;
            gg[i].cost = c;
            sum += c;
        }
        beg = 1;
        int cnt = 0;
        for (i = 1; i <= n; i++)
        {
            if (d[i] & 1)
            {
                cnt++;
                sg[cnt] = i;
                beg = i;
            }
        }
        if (!cnt)
        {
            printf("sum=%d\n", sum);
            Fleury(beg);
            Print_Path();
        }
        else
        {
            Floyed();
            printf("sum=%d\n", sum + ADD(cnt));
            AddPath(cnt);
            Fleury(beg);
            Print_Path();
        }
    }
}
int main()
{
    CNLoad();
    return 0;
}

测试用例:(图结构)

输出结果:

相关推荐
何曾参静谧29 分钟前
「C/C++」C/C++ 之 变量作用域详解
c语言·开发语言·c++
AI街潜水的八角39 分钟前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
JSU_曾是此间年少1 小时前
数据结构——线性表与链表
数据结构·c++·算法
此生只爱蛋2 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
何曾参静谧2 小时前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
lulu_gh_yu3 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
ULTRA??4 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者4 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者4 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
~yY…s<#>5 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode