欧拉路径&&欧拉回路

定义:

欧拉路径:指图中的一条路径,使得所有边都被经过且只经过一次

欧拉回路:指图中的一条欧拉路径,且起点和终点相同。

欧拉图:指有欧拉回路的图

半欧拉图:指有欧拉路径但没有欧拉回路的图

性质:

1.如果一个无向图是欧拉图,那么所有节点的度数均为偶数

2.如果一个无向图是半欧拉图,那么除了两个节点的度数为奇数,其他的节点度数都为偶数

3.如果一个有向图是欧拉图,那么对于每个节点,它的入度和出度相等。

4.如果一个有向图是半欧拉图,那么除了两个节点的入出度差为 \(1\) 以外,其他节点入出度差都为 \(0\)(即相等)。

HierHolzer:

problem:

给定图 \(G\),求 \(G\) 中字典序最小的欧拉路径

solution:

先考虑生成欧拉路径:

1.找到出度减入度为 \(1\) 的节点(假如没有默认为 1 号节点),将其作为起始节点进行 \(dfs\)

2.考虑 \(u\) 节点未访问过的边 \((u,v)\),如果没有,将 \(u\) 节点压入栈并返回。

3.标记 \((u,v)\) 为已访问。

4.对 \(v\) 进行2,3操作。

5.所有操作完成后,将栈中元素输出。

通过这里我们知道,元素是倒序输出的,所以我们要让后面的元素尽量小,所以其实就是要将链式前向星中的元素从大到小排序。

代码:


#include<bits/stdc++.h>
#define int long long 
using namespace std;

const int N=1e5+10;
struct edge{
	int v,next;
}edges[N*2];
int head[N],idx;
int n,m; 

void add_edge(int u,int v){
	idx++;
	edges[idx].v=v;
	edges[idx].next=head[u];
	head[u]=idx;
	return;
}

int stk[N*3],top;
void dfs(int u){
	for(int i=head[u];i;i=head[u]){
		int v=edges[i].v;
		head[u]=edges[i].next;
		dfs(v);
	} 
	stk[++top]=u;
	return;
}

int degin[N],degout[N];

struct stu{
	int u,v;
}st[N*2];
bool cmp(struct stu st1,struct stu st2){
	if(st1.u==st2.u)return st1.v>st2.v;
	return st1.u>st2.u;
}

signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>st[i].u>>st[i].v; 
	}
	sort(st+1,st+m+1,cmp);
	for(int i=1;i<=m;i++){
		add_edge(st[i].u,st[i].v);
		degin[st[i].v]++;
		degout[st[i].u]++;
	}
	int s=1,cnt=0;
	for(int i=1;i<=n;i++){
		if(abs(degin[i]-degout[i])&1)cnt++;
		if(degout[i]-degin[i]==1)s=i;
	}
	if(cnt!=2&&cnt!=0){
		cout<<"No"<<endl;
		return 0;
	}
	dfs(s);
	while(top>0){
		cout<<stk[top]<<" ";
		top--;
	}
	
	return 0;
}

posted @ 2024-04-25 13:04  Little_corn  阅读(12)  评论(0编辑  收藏  举报