把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

欧拉路与欧拉回路

欧拉路与欧拉回路的定义

如果一张图中的一个路径包括每个边恰好一次,则该路径称为欧拉路

如果一个回路是欧拉路,则称为欧拉回路

欧拉路与欧拉回路的存在条件

  • 对于无向联通图
    • 欧拉路:只有两个点为奇点的无向图存在欧拉路(起点和终点为两个奇点)。
    • 欧拉回路:没有奇点的无向图存在欧拉回路。
  • 对于有向联通图
    • 欧拉路:一个顶点的出度-入度=1,另一个顶点的入度-出度=1,其他所有点入度等于出度时存在欧拉路(起点为出度-入度=1的点,终点为入度-出度=1的点)。
    • 欧拉回路:所有点的入度等于出度时存在欧拉回路。

如何求解欧拉路与欧拉回路

我们从确定的起点出发(欧拉回路可以从任意一个节点出发),然后枚举每一条与当前节点相连的边,不停地向下一个节点走,并把走过的边从图中删去。每次把到达当前节点所经过的边加入统计答案的\(res[\) \(]\)数组中,可以证明,这样一定能找到一组合法的解。

代码

inline void dfs(int x,int lst)//dfs跑欧拉回路(无向图版)
{
	register int &i=lnk[x];//注意,此处的i前面要加一个&,这样就可以不停修改lnk[x],起到一定的优化效果
	for(;i;i=e[i].nxt)//枚举下一条边
	{
		if(vis[i+1>>1]) continue;//如果这条边已经访问过了,就跳过
		vis[i+1>>1]=1,dfs(e[i].to,i&1?(i+1>>1):-(i+1>>1));//标记这条边已访问,搜索下一个点,记录是由这条边通往下一个点的
	}
	if(lst) res[++res_]=lst;//如果不是起点,就记录下到达当前节点的边
}
inline void dfs(int x,int lst)//dfs跑欧拉回路(有向图版),大致思想同上
{
	register int &i=lnk[x];
	for(;i;i=e[i].nxt)
	{
		if(vis[i]) continue;
		vis[i]=1,dfs(e[i].to,i);
	}
	if(lst) res[++res_]=lst;
}

例题

【洛谷1341】无序字母对

posted @ 2018-10-28 21:37  TheLostWeak  阅读(269)  评论(0编辑  收藏  举报