【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

代码

#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;
      }
posted @ 2025-07-27 22:04  yfceshi  阅读(3)  评论(0)    收藏  举报