欧拉回路
(1) 图的深度优先遍历
#include <iostream>
using namespace std;
int Node, Edge, Node1, Node2;
struct List_Node {
int Node, Next;
List_Node() {
Node = 0;
Next = 0;
}
List_Node(int node, int next) {
Node = node;
Next = next;
}
};
List_Node List[1005];
int Head[105];
int New = 1;
void Insert(int Node1, int Node2) {
List[New] = List_Node(Node2, Head[Node1]);
Head[Node1] = New;
New++;
}
bool Visited[105];
void DFS(int StartId) {
Visited[StartId] = true;
cout << StartId << ' ';
for (int i = Head[StartId]; i != 0; i = List[i].Next) {
if (Visited[List[i].Node] == false) {
DFS(i);
}
}
}
void Search() {
for (int i = 1; i <= Node; i++) {
if (Visited[i] == 0) DFS(i);
}
}
int main() {
cin >> Node >> Edge;
for (int i = 1; i <= Edge; i++) {
cin >> Node1 >> Node2;
Insert(Node1, Node2);
Insert(Node2, Node1);
}
Search();
return 0;
}
时间复杂度分析
每一个顶点被访问一次
每条边被访问两次
O(|V|+|E|)
O(|V|2) 对稠密图 |E|~|V|2
O(|V|) 对稀疏图 |E|~|V|
注意:
爆栈问题
(2) 应用举例——欧拉路 (一笔画) 问题
定义
欧拉路或欧拉回路问题,
就是有一条路径(或回路)由所有边构成,且每边只用一次。也称为一笔画问题,即连续的一次画出图的所有边,经过每条边一次且仅一次。
结论1:无向图存在欧拉回路的必要条件:
- 图是连通的。
- 图中所有点的度均为偶数。
结论2:无向图欧拉路存在的必要条件:
- 图是连通的。
- 图中有且仅有两个度为奇数的点,并且这两个点一定是这条欧拉路的起点与终点。
证明
- “勇往直前”
- “圈套圈”
- 把欧拉回路构造出来
结论3:有向图G,存在欧拉回路的必要条件:
- 基图(原有向边改为无向边后所得的无向图)连通
- 所有点的出度和入度相同
结论4:有向图G,存在欧拉路的必要条件:
- 基图连通
- 有且仅有一个点入度比出度大1,且这个点是欧拉路的终点
- 有且仅有一个点入度比出度小1,且这个点是欧拉路的起点
- 其他所有的点入度与出度相等
无向图的邻接矩阵递归程序
#include <cstdio>
using namespace std;
int Node, Edge, Node1, Node2;
bool Graph[105][105];
void DFS(int Now_Node) {
for (int i = 1; i <= Node; i++) {
if (Graph[Now_Node][i] || Graph[i][Now_Node]) {
Graph[Now_Node][i] = 0;
Graph[i][Now_Node] = 0;
}
}
printf("%d ", Now_Node);
}
int main() {
scanf("%d%d", &Node, &Edge);
for (int i = 1; i <= Edge; i++) {
scanf("%d%d", &Node1, &Node2);
Graph[Node1][Node2] = Graph[Node2][Node1] = true;
}
DFS(1);
return 0;
}