【PTA数据结构 | C语言版】哥尼斯堡的“七桥问题”

本专栏持续输出数据结构题目集,欢迎订阅。

文章目录

题目

哥尼斯堡是位于普累格河上的一座城市,它包含两个岛屿及连接它们的七座桥,如下图所示。

可否走过这样的七座桥,而且每桥只走过一次?瑞士数学家欧拉(Leonhard Euler,1707---1783)最终解决了这个问题,并由此创立了拓扑学。

这个问题如今可以描述为判断欧拉回路是否存在的问题。欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个无向图,问是否存在欧拉回路?

输入格式:

输入第一行给出两个正整数,分别是节点数 n (1≤n≤1000)和边数 m;随后的 m 行对应 m 条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到 n 编号)。

输出格式:

若欧拉回路存在则输出 1,否则输出 0。

输入样例1:

6 10

1 2

2 3

3 1

4 5

5 6

6 4

1 4

1 6

3 4

3 6

输出样例1:

1

输入样例2:

5 8

1 2

1 3

2 3

2 4

2 5

5 3

5 4

3 4

输出样例2:

0

代码

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

#define MAX_N 1000

// 邻接表节点结构
typedef struct Node {
    int vertex;
    struct Node* next;
} Node;

// 并查集结构
typedef struct {
    int parent[MAX_N + 1];
    int rank[MAX_N + 1];
} UnionFind;

// 初始化并查集
void initUnionFind(UnionFind* uf, int n) {
    for (int i = 1; i <= n; i++) {
        uf->parent[i] = i;
        uf->rank[i] = 1;
    }
}

// 查找根节点并路径压缩
int find(UnionFind* uf, int x) {
    if (uf->parent[x] != x) {
        uf->parent[x] = find(uf, uf->parent[x]);
    }
    return uf->parent[x];
}

// 合并两个集合
void unionSets(UnionFind* uf, int x, int y) {
    int xRoot = find(uf, x);
    int yRoot = find(uf, y);
    
    if (xRoot == yRoot) return;
    
    if (uf->rank[xRoot] < uf->rank[yRoot]) {
        uf->parent[xRoot] = yRoot;
    } else if (uf->rank[xRoot] > uf->rank[yRoot]) {
        uf->parent[yRoot] = xRoot;
    } else {
        uf->parent[yRoot] = xRoot;
        uf->rank[xRoot]++;
    }
}

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    
    // 记录每个顶点的度数
    int degree[MAX_N + 1] = {0};
    
    // 初始化并查集
    UnionFind uf;
    initUnionFind(&uf, n);
    
    // 处理每条边
    for (int i = 0; i < m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        
        // 更新度数
        degree[u]++;
        degree[v]++;
        
        // 合并两个顶点所在的集合
        unionSets(&uf, u, v);
    }
    
    // 检查所有边是否在同一个连通分量中
    int root = -1;
    int hasEdge = 0;
    
    for (int i = 1; i <= n; i++) {
        if (degree[i] > 0) {
            hasEdge = 1;
            if (root == -1) {
                root = find(&uf, i);
            } else if (find(&uf, i) != root) {
                // 存在多个连通分量
                printf("0\n");
                return 0;
            }
        }
    }
    
    // 如果没有边,特殊处理
    if (!hasEdge) {
        printf("0\n");
        return 0;
    }
    
    // 检查所有顶点的度数是否为偶数
    for (int i = 1; i <= n; i++) {
        if (degree[i] % 2 != 0) {
            printf("0\n");
            return 0;
        }
    }
    
    // 所有条件满足,存在欧拉回路
    printf("1\n");
    
    return 0;
}    
相关推荐
Christo31 分钟前
TKDE-2026《Efficient Co-Clustering via Bipartite Graph Factorization》
人工智能·算法·机器学习·数据挖掘
啟明起鸣1 分钟前
【Nginx 网关开发】上手 Nginx,简简单单启动一个静态 html 页面
运维·c语言·前端·nginx·html
2401_838472511 分钟前
C++异常处理最佳实践
开发语言·c++·算法
m0_736919105 分钟前
C++中的类型标签分发
开发语言·c++·算法
卡里笔记5 分钟前
C语言版2048小游戏
c语言
2301_7903009612 分钟前
C++与微服务架构
开发语言·c++·算法
重生之我是Java开发战士18 分钟前
【优选算法】前缀和:一二维前缀和,寻找数组的中心下标,除自身以外数组的乘积,和为K的子数组,和可被K整除的子数组,连续数组,矩阵区域和
线性代数·算法·矩阵
梵刹古音20 分钟前
【C语言】 循环结构
c语言·开发语言·算法
bbq粉刷匠27 分钟前
Java-排序2
java·数据结构·排序算法
皮皮哎哟28 分钟前
冒泡排序与数组传递全解析 一维二维指针数组及二级指针应用指南
c语言·算法·冒泡排序·二维数组·指针数组·传参·二级指针