案例6-1.3 哥尼斯堡的“七桥问题” (25分)
哥尼斯堡是位于普累格河上的一座城市,它包含两个岛屿及连接它们的七座桥,如下图所示。
可否走过这样的七座桥,而且每桥只走过一次?瑞士数学家欧拉(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
这道题我最开始的思路是:对每条边增加一个标记,记录该边是否走过。看最后能否实现走过了所有的边后回到最初点。
用这种思路编程,前三个测试点都能通过,最后两个测试点运行超时。
后来在网上看到了别人的一篇博客(原文链接https://blog.csdn.net/treblez/article/details/100996249):
存在欧拉回路需满足两个条件:
1.无向图连通
2.所有结点的度全部为偶数
我用邻接矩阵存储无向图。
判断无向图连通我是先深度优先搜索DFS遍历图,再遍历Visited数组,判断是否所有的结点都被访问过。如果所有结点都被访问过,则无向图连通;否则,不连通,不存在欧拉回路。
再对每个结点逐个判断度是否为偶数,求出某结点的邻接矩阵对应行中的非零元素总个数,若为奇数,则不存在欧拉回路;若所有结点的度均为偶数,且图连通,则存在欧拉回路。
C语言实现:
#include<stdio.h>
#include<stdlib.h>
struct edge
{
int vs;
int ve;
};
typedef struct edge * Edge;
struct graph //邻接矩阵存储图
{
int Nv;
int Ne;
int * * M;
};
typedef struct graph * Graph;
Graph CreateGraph(int N);
void DFS(Graph G, int i);
int * Visited;
int main()
{
int i;
int N, M;
scanf("%d %d", &N, &M);
Visited = (int *)malloc(N * sizeof(int));
for (i = 0; i < N; i++)
{
Visited[i] = 0;
}
Graph G;
G = CreateGraph(N);
G->Ne = M;
int v1, v2;
int yes;
Edge * e;
e = (Edge *)malloc(M * sizeof(Edge));
for (i = 0; i < M; i++)
{
e[i] = (Edge)malloc(sizeof(struct edge));
}
for (i = 0; i < M; i++)
{
scanf("%d %d", &v1, &v2);
e[i]->vs = v1 - 1;
e[i]->ve = v2 - 1;
G->M[v1 - 1][v2 - 1] = 1;
G->M[v2 - 1][v1 - 1] = 1;
}
//判断图是否连通
DFS(G, 0); //深度优先搜索DFS遍历图
for (i = 0; i < N; i++)
{
if (Visited[i] == 0) { yes = 0; break; }//是否有未访问的结点
}
if (i == N)
{
//判断各结点的度是否均为偶数
yes = 1;
int j;
int du = 0;//记录结点的度
for (i = 0; i < N; i++)
{
du = 0;
for (j = 0; j < N; j++)
{
if (G->M[i][j] == 1)
{
du++;
}
}
if (du % 2 == 1)
{
yes = 0;
break;
}
}
}
if (yes == 1) { printf("1"); }
else { printf("0"); }
return 0;
}
Graph CreateGraph(int N) //创建图
{
int i, j;
Graph G;
G = (Graph)malloc(sizeof(struct graph));
G->Nv = N;
G->M = (int * *)malloc(N * sizeof(int *));
for (i = 0; i < N; i++)
{
G->M[i] = (int *)malloc(N * sizeof(int));
}
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
G->M[i][j] = 0;
}
}
return G;
}
void DFS(Graph G, int i) //深度优先搜索遍历
{
int j;
Visited[i] = 1;
for (j = 0; j < G->Nv; j++)
{
if (G->M[i][j] == 1 && Visited[j] == 0)
{
DFS(G, j);
}
}
}