【图的应用】——哥尼斯堡的“七桥问题” (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

连续两天没做题了,最近家里事情好多,烦得很,复习的时间都没有,更别说坐下来好好思考题了,从来没有这么慌过考试。。。服了,还是上学好,事少,希望考试不要翻车
欧拉回路怎么判断,充要条件是啥?忘了。这就忘了?是,我真的忘了。怕是离散上了个寂寞。刚开始想用并查集判断是否连通,遍历的时候看起点和终点是否相等,被第二个点难到了,不知道如何判断比较好,参考网上思路和代码,发现欧拉回路还可以这么求(说这句话对得起温柔的wangmeng老师吗)——对于无向图来说,每个结点的度都是偶数,用的dfs,后边有并查集做法(大佬代码,这个大佬算法好厉害)
#include <iostream>
using namespace std;

int n,m;
int graph[1001][1001];
int vis[1001];

void dfs(int cur){
	vis[cur] = 1;
	for(int i = 1;i<=n;i++){
		if(graph[cur][i]&&!vis[i])
			dfs(i);
	}
} 

int deg(int cur){
	int count = 0;
	for(int i = 1;i<=n;i++){
		if(graph[cur][i])
			count++;
	}
	return count;
}

int main(){
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i = 0;i<m;i++){
		int v1,v2;
		cin >> v1 >> v2;
		graph[v1][v2] = graph[v2][v1] = 1;
	}
	dfs(1);
	int flag = 1;
	for(int i = 1;i<=n;i++){
		if(deg(i)%2!=0||!vis[i]){
			flag = 0;
			break;
		}
	}
	cout << flag;
    return 0;
}
并查集做法
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

#define MAXSIZE 10005

vector<int> v[MAXSIZE];//用于存放每个点与哪个点连接
int pre[MAXSIZE];//并查集数组,用于存放每个元素的父结点

int find(int x){
	if(pre[x]==-1)
		return x;
	else
		return pre[x] = find(pre[x]);
} 

void merge(int x,int y){//判断是否连通,不连通就合并 
	if(find(x)!=find(y))//如果不连通,就把它们所在的连通分支合并 
		pre[find(y)] = find(x);
}

int main(){
	ios::sync_with_stdio(false);
	int n,m;
	cin >> n >> m;
	memset(pre,-1,sizeof(pre));//并查集数组初始化
	int t1,t2;
	for(int i = 1;i<=m;i++){
		cin >> t1 >> t2;
		merge(t1,t2);
		//把对方分别放进自己的数组
		v[t1].push_back(t2);
		v[t2].push_back(t1); 
	} 
	int count = 0;//统计奇数点
	int num = 0;//统计祖先个数,如果只有一个证明是连通图
	for(int i = 1;i<=n;i++){
		if(v[i].size()%2)
			count++;
		if(find(i)==i)
			num++;
	} 
	if(count==0&&num==1)
		cout << 1 << endl;
	else
		cout << 0 << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45845039/article/details/108252063