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

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

程序流程图:

数学原理:

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

时间复杂度分析:

        程序的时间复杂度主要来自于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)

源代码:

#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;
}

测试用例:(图结构)

输出结果:

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 14:42:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 14:42:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 14:42:03       45 阅读
  4. Python语言-面向对象

    2024-07-10 14:42:03       55 阅读

热门阅读

  1. 这道笔试题,给了我一点小小的c语言震撼

    2024-07-10 14:42:03       16 阅读
  2. python压缩PDF方案(Ghostscript+pdfc)

    2024-07-10 14:42:03       19 阅读
  3. 掌握Perl命令行:深入解析命令行参数的艺术

    2024-07-10 14:42:03       26 阅读
  4. 【计算机网络】tcp协议和upd协议有什么区别

    2024-07-10 14:42:03       23 阅读
  5. hnust 1966: 广度优先搜索

    2024-07-10 14:42:03       20 阅读
  6. kubekey在ubuntu24实现kubernetes快速安装

    2024-07-10 14:42:03       21 阅读