首页 > 其他分享 >【欧拉回路小记】

【欧拉回路小记】

时间:2022-09-03 10:13:49浏览次数:76  
标签:ch 一个点 int 路径 回路 欧拉 小记

模板

条件

  1. 无向图存在欧拉回路的充要条件是任意一个点的度数都为偶数,且所有的边是联通的(也就是除去孤立点外,图是连通的)
  2. 有向图存在欧拉回路的充要条件是任意一个点的入度等于其出度,且忽略边的方向后,边是连通的(同上,等价于除去孤立点外,图是连通的)
  3. 无向图存在欧拉路径的充要条件是有且仅有两个点的度数为奇数,其余为偶数,边的连通性同上
  4. 有向图存在欧拉路径的充要条件是有且仅有一个点出度比入度大1(作为起点),一个点入度比出度大1(作为终点),其余点入度等于出度,边的连通性同上
    (为了方便,这里的欧拉路径没有把回路包括在内)
    证明:
    上述条件的必要性是显然的,考虑证明其充分性,也就是对于任意满足条件的图,构造出一组解。
    以无向图的欧拉路径为例,首先找到任意一条从起点到终点的路径(不难发现,这样的路径一定存在),然后把这条路径的边和孤立点都删去,那么剩下的子图一定都与这条路径有交点,在剩下的子图中找到一条欧拉回路然后接到这个路径上就可以了。
    在子图中找欧拉回路可以递归去做,即先找到一个环,然后从环上的每个点出发再找一条欧拉回路……

算法流程

以无向图欧拉回路为例
与上述的构造类似,我们考虑这样一个过程:先从任意一个点(作为起点)出发,走一个回路(不一定是简单环)回到这个点,再从环上的每个点找这个点的欧拉回路,然后把这些欧拉回路插到一开始找到的大环中,这样可以用链表来维护复杂度为线性。
但是实际上用一个dfs+栈就够了。直接从起点开始dfs,那么第一次回溯一定是在终点(如果是欧拉回路则还是起点),把回溯的这条边作为欧拉路的最后一条边,然后回溯到上一个点x,继续从x进行dfs找欧拉回路并倒序压入栈中,然后再回溯,再找欧拉回路持续这样的过程,最终把从栈顶到栈底输出即为答案。

细节

  1. 为了避免重复访问已经被删除的边,要用一个数组存下每个点最后用的过的一条边,每次在邻接表上跳下一条边时不再跳nxt[i],而是nxt[cur[x]]
  2. 判欧拉回路边的连通性可以用并查集,也可以先当成连通来做,看最后找到的欧拉回路的总边数是否等于原图的总边数。

代码

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

int rd()
{
	int x=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)&&ch!='-') ch=getchar();
	if(ch=='-') ch=getchar(),w=-1;
	while(isdigit(ch)) x=x*10+(ch-48),ch=getchar();
	return x*w;
}
const int N=2e5+100;
int n,m,ind[N],od[N],deg[N],hd[N],cnt=1,fa[N<<1];
struct node{
	int nxt,to,id;
}e[N<<1];
int vis[N<<1];
int op,stk[N<<1],top;
int find(int x)
{
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
void dfs(int x)
{
//	cout<<hd[x]<<endl;
//	if(hd[x]==3){
//		puts("jjjjlllll");
//	}
	for(int i=hd[x];i;i=e[hd[x]].nxt)
	{
		hd[x]=i;
		if(vis[i]) continue;
		vis[i]=1;if(op&1) vis[i^1]=1;
		dfs(e[i].to);
		stk[++top]=e[i].id;
	}
}
void add(int x,int y,int id)
{
	++cnt;
	e[cnt]={hd[x],y,id};
	hd[x]=cnt;
}
signed main()
{
//	freopen("data.in","r",stdin);
    op=rd();n=rd();m=rd();for(int i=1;i<=n+m;++i) fa[i]=i;
    if(op&1)
    {
    	for(int i=1;i<=m;++i){
    		int x=rd(),y=rd();
    		int fx=find(x),fy=find(y);
    		fa[fx]=fy;fa[n+i]=fy;
    		add(x,y,i);deg[x]++;
    		add(y,x,-i);deg[y]++;
		}
//		for(int i=1;i<=n;++i) cout<<deg[i]<<endl;
		for(int i=1;i<=n;++i) if(deg[i]&1) {
			puts("NO");return 0;
		}
		for(int i=2;i<=m;++i) if(find(n+i)!=find(n+i-1)){
			puts("NO");return 0;
		}
		puts("YES");
		for(int i=1;i<=n;++i) dfs(i);
		while(top) cout<<stk[top--]<<' ';
		return 0;
	}
	for(int i=1;i<=m;++i){
		int x=rd(),y=rd();
		add(x,y,i);ind[y]++;od[x]++;
		int fx=find(x),fy=find(y);
		fa[fx]=fy;fa[n+i]=fy;
	}
	for(int i=1;i<=n;++i) if(ind[i]!=od[i]){
		puts("NO");return 0;
	}
	for(int i=2;i<=m;++i) if(find(i+n)!=find(i+n-1)){
		puts("NO");return 0;
	}
	puts("YES");
	for(int i=1;i<=n;++i) dfs(i);
	while(top) cout<<stk[top--]<<' ';
	return 0;
}

标签:ch,一个点,int,路径,回路,欧拉,小记
From: https://www.cnblogs.com/glq-Blog/p/16652040.html

相关文章

  • 欧拉筛素数及积性函数
    欧拉筛素数及积性函数欧拉筛素数intPrime[N],tot;boolNot[N];//true则i不是素数voidGetPrime(constint&n=N-1){Not[1]=true;for(inti=2......
  • go map键类型小记
    一、Go语言map的键类型不可以是函数类型、字典类型和切片类型。因为map键值需要可以做hash操作,而func,map,slice不支持这些操作。 报错:  并且,一般Struct可以支持ha......
  • 欧拉反演与它的证明
    就是证明,用狄利克雷卷积做,欧拉反演狗都不用/oh\(\sum\limits_{d|n}\varphi(d)=n\)。长得很像狄利克雷卷积,令\(g(n)\)恒等于\(1\),作\(\varphi(n)\)与\(g(n)\)的......
  • 使用WangEditor4+KityFormula处理公式编辑业务(小记)
    一开始,直接套用了mirror29在github的样板代码,整体挺好用的(感谢mirror29)。不过在具体的集成过程中,自己调整了原有的一些交互细节并处理了一些特定操作可能会触发的错误,已提......
  • 小记 【django git python】
    迁移此处生成的迁移文件包含了所有的表结构(已创建和未创建的表)pythonmanage.pymakemigrationsapp_namepythonmanage.pymigrate--fake-initial--fake-initial的......
  • esxi主机升级小记
    1、上传补丁包,首先打开ESXI主机的ssh  2、然后SSH登录并找到主机并进入离线包所在目录下3、检查补丁包信息esxclisoftwaresourcesprofilelist--depot=/vmfs/v......
  • 【DP】决策单调性小记
    何谓决策单调性?指的就是在最优化dp中,状态的最优转移点单调不减的性质。这使得我们在做dp的时候可以减少冗余计算以达到优化的效果。这类优化方法常用于分段问题。0x......
  • 8.23-8.25小记
    因为成都太热了就在家上网课,很开心的。然后摸了几个题。题目名算法感悟CF1023G最小链覆盖=最大反链;dsuontree感觉难搞的是ds部分呢。善用map.jpgCF1322E......
  • storm性能优化小记
     1、默认情况下:1个supervisor节点启动4个worker进程。每一个topology默认占用一个worker进程。每个worker会启动executor。每个executor默认启动一个task。 2、并......
  • 哈密顿回路
    https://www.acwing.com/problem/content/description/1617/思路:需要满足:1.第一个点和最后一个点相同,这样才能形成回路。2.要有恰好有n+1个点,因为哈密顿回路本身就要......