哥尼斯堡的“七桥问题” (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
相关知识:
欧拉回路:在图G中若存在一条路,经过G中每条边有且仅有一次,称这条路为欧拉路,如果存在一条回路经过G每条边有且仅有一次,称这条回路为欧拉回路。具有欧拉回路的图成为欧拉图。
判断欧拉路是否存在的方法
有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。
无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。
判断欧拉回路是否存在的方法
有向图:图连通,所有的顶点出度=入度。
无向图:图连通,所有顶点都是偶数度。
1.凡是由偶点组成的连通图,一定可以一笔画成。
2.凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成。
3.其他情况的图都不能一笔画出。
我的代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define MAXSIZE 10005 5 vector<int> v[MAXSIZE]; //用于存放每个点与哪个点连接 6 int pre[MAXSIZE]; //并查集数组,用于存放每个元素的父节点 7 int Find(int x); //并查集搜索,寻找根结点 8 void link(int x,int y); //判断是否联通,不连通就合并 9 10 int main() 11 { 12 ios::sync_with_stdio(false); //取消cin和stdin的同步 13 int N,M; //结点数N,边数M 14 cin >> N >> M; 15 memset(pre,-1,sizeof(pre)); //并查集数组初始化 16 int a,b; 17 for (int i = 1; i <= M; i++) //输入第i条边直接联通的俩个节点的编号 18 { 19 cin >> a >> b; 20 link(a,b); //连接 21 //把对方分别放进自己的数组 22 v[a].push_back(b); 23 v[b].push_back(a); 24 } 25 int count = 0; //count用来统计奇数点(与其他点有奇数个连接) 26 int num = 0; //num用来统计老祖宗个数,老祖宗有且仅有一个说明是连通图 27 for (int i = 1; i <= N; i++) 28 { 29 if (v[i].size() % 2) 30 { 31 count++; 32 } 33 if (Find(i) == i) 34 { 35 num++; 36 } 37 } 38 if (count == 0 && num == 1) //当俩个都是偶数点且只有一个老祖宗时,是欧拉回路 39 { 40 cout << 1 << endl; 41 } 42 else 43 { 44 cout << 0 << endl; 45 } 46 return 0; 47 } 48 49 int Find(int x) //并查集搜索 50 { 51 if(pre[x] == -1) //判断是不是老祖宗 52 { 53 return x; 54 } 55 else 56 { 57 return pre[x] = Find(pre[x]); 58 } 59 } 60 61 void link(int x,int y) //判断是否联通,不连通就合并 62 { 63 if(Find(x)!=Find(y)) //如果不连通,就把它们所在的连通分支合并 64 { 65 pre[Find(y)] = Find(x); 66 } 67 }