欧拉回路模板

欧拉回路 \huge \textbf{欧拉回路} 欧拉回路

欧拉回路即一笔画问题 \textsf{欧拉回路即一笔画问题} 欧拉回路即一笔画问题

[ 题目链接 ] ( h t t p s : / / w w w . l u o g u . c o m . c n / p r o b l e m / P 7771 ) [题目链接](https://www.luogu.com.cn/problem/P7771) [题目链接](https://www.luogu.com.cn/problem/P7771)

这是一道模板题 这是一道模板题 这是一道模板题

能否构成欧拉回路要满足以下几点 \large{能否构成欧拉回路要满足以下几点} 能否构成欧拉回路要满足以下几点

有向图 \quad 有向图 有向图

1 ⋅ 所有点入度出度相等 \qquad1 \centerdot所有点入度出度相等 1所有点入度出度相等
2 ⋅ 如果又不相等的点则必须有两个,一个入度 − 出度 = 1 (终点),另一个出度 − 入度 = 1 (起点) \qquad2 \centerdot如果又不相等的点则必须有两个,一个入度 - 出度 = 1(终点),另一个出度 - 入度 = 1(起点) 2如果又不相等的点则必须有两个,一个入度出度=1(终点),另一个出度入度=1(起点)

无向图 \quad 无向图 无向图

1 ⋅ 所有点恰好有偶数条边 \qquad1 \centerdot所有点恰好有偶数条边 1所有点恰好有偶数条边
2 ⋅ 有且仅有 2 个点有奇数条边(一个为起点一个为终点) \qquad2 \centerdot有且仅有2个点有奇数条边(一个为起点一个为终点) 2有且仅有2个点有奇数条边(一个为起点一个为终点)
在上述 1 的情况下,以任意一点为起点,则可以不重复的走遍所有路径回到该点 在上述1的情况下,以任意一点为起点,则可以不重复的走遍所有路径回到该点 在上述1的情况下,以任意一点为起点,则可以不重复的走遍所有路径回到该点

下面给出两种不同存图方式的代码 下面给出两种不同存图方式的代码 下面给出两种不同存图方式的代码

邻接矩阵 \small \textbf{邻接矩阵} 邻接矩阵

#include<iostream>
#include<cmath> 
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

int map[510][510];
int n = 1,m;
int ans = 0;
int f[1025],num[510];

void Euler(int now){
	for(int i = 1; i <= n; i ++)
		if(map[now][i] != 0){
			map[now][i] --;
			map[i][now] --;
			Euler(i);
		}
	f[++ ans] = now;
}

int main(){
	cin>>m;
	memset(map,0,sizeof(map));
	memset(num,0,sizeof(num));
	for(int i = 1; i <= m; i ++){
		int u,v;
		cin>>u>>v;
		n = max(n,u);
		n = max(n,v);
		map[u][v] ++;
		map[v][u] ++;
		num[u] ++;
		num[v] --;
	}
	int s = 1;
	for(int i = 1; i <= n; i ++)
		if(num[i] % 2){
			s = i;
			break;
		}
	Euler(s);
	for(int i = m + 1; i >= 1; i --)
		cout<<f[i]<<endl;
	return 0;
}

邻接链表 \small \textbf{邻接链表} 邻接链表

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>

using namespace std;

const int MAX = 100010;
int n,m,u,v,del[MAX];
int num[MAX];

stack<int> st;
vector<int> map[MAX];

void Euler(int now){
	for(int i = del[now]; i < map[now].size(); i = del[now]){
		del[now] = i + 1;
		Euler(map[now][i]);
	}
	st.push(now);
}

int main(){
	cin>>n>>m;
	for(int i = 1; i <= m; i ++){
		int u,v;
		cin>>u>>v;
		map[u].push_back(v);
		num[u] ++;
		num[v] --;
	}
	for(int i = 1; i <= n; i ++) sort(map[i].begin(),map[i].end());
	int s = 1,cnt[2] = {0,0};
	bool flag = 1;
	for(int i = 1; i <= n; i ++){
		if(num[i] != 0) flag = 0;
		if(num[i] == 1) cnt[1] ++,s = i;
		if(num[i] == -1) cnt[0] ++;
	}
	if((!flag)&&!(cnt[0]==cnt[1]&&cnt[0]==1)) return !printf("No");
	Euler(s);
	while(!st.empty()){
		cout<<st.top()<<" ";
		st.pop();
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值