欧拉图
欧拉图通路(回路):通过图中所有边一次且仅一次,并且过每一顶点的通路(回路)
无向图判断
G有欧拉通路:G连通,且G中奇数度的点只有0或2个。
G有欧拉回路:G连通,且G中都是偶数度点(奇数度点为零)。
有向图判断
D有欧拉通路:D连通,除两个顶点外(只有两个),其余顶点的入度等于出度。这两个顶点一个出度比入度大1,一定是起点;另一个入度比出度大1,一定是终点(只能大1,且总共两个这样的点)。
D有欧拉回路:D连通,D中所有点的入度等于出度。
欧拉图典型的问题有单词拼接,一笔画问题,其解题步骤大概相同
第一步:根据有向图或无向图的条件,判断是否具有欧拉通路(回路);
第二步:在判断是否连通(dfs或并查集)一般判断连通:遍历节点次数是否等于节点总数。如果是通路:一定要从起点开始遍历。
dfs方法:
//利用了单词拼接的dfs模板
int dfs(int k,int cnt){//深搜构造欧拉通路 k起点,cnt遍历次数
if(cnt==m) return 1;//连通
for(int i=0;i<m;i++){
if(k!=s[i].s||vis[i]) continue;
vis[i]=1;
jie[cnt]=i;//记录路径
if(dfs(s[i].e,cnt+1)) return 1;
vis[i]=0;//回溯
}
return 0;//不连通
}
还有一种:
void euler (int k){
for(int i=0;i<m;i++){
if(k==s[i].s&&!vis[i]){//找符合条件的单词 (k==s[i].s意思:挑选符合的入度节点)
vis[i]=1;
euler(s[i].e);//以这个单词的结尾找下一个的开头 euler(出度指向的节点)
q.push(s[i]);//递归从下自上,终点进栈保证顺序输出,如果是printf则是倒序
}//printf写在这也是倒序
}
}
上面这个函数不用回溯,因为是一找到底,再也找不到连通的下一个节点时,这个点必是终点,标记进栈,for循环再找,又有再也找不到连通的下一个节点时,这是联通的倒数第二个节点,进栈,再找.........,直到for执行完。这是构造了一条路,是否联通只需要判断栈中元素是否为n(节点总数),是则连通。