Skip to content

Latest commit

 

History

History
23 lines (12 loc) · 2.68 KB

File metadata and controls

23 lines (12 loc) · 2.68 KB

2097.Valid-Arrangement-of-Pairs

因为本题保证一定有解,所以这就是一个欧拉路径问题:我们将每个数字当做节点,每个pair看做是两个节点之间的路径,那么本题就是规划一条路径,要求不重复地走过所有边。类似的题目有LC332。

对于欧拉路径,我们回顾一下相关的知识点:

欧拉路径:从一个点出发,到达另外一个点,所有的边都经过且只经过1次。

欧拉回路:欧拉路径中,终点能回到起点。

如果判断是否存在欧拉路径?

1.无向图:(a) 如果只有两个点的度是奇数,其他的点的度都是偶数,则存在从一个奇数度点到另一个奇数度点的欧拉路径(不是回路)。(b) 如果所有的点的度都是偶数,那么就是欧拉回路。

2.有向图:(a) 如果最多有一个点出度大于入度by1,且最多有一个点入度大于出度by1,那么就有一条从前者(如果没有则可以任意)到后者(如果没有则可以任意)的欧拉路径。(b) 如果所有的点的入度等于出度,那么就存在欧拉回路。

对于本题而言,我们只要根据有向图的规则,找到出度-入度==1的那个点作为起点。如果不存在,就可以任意为起点。

那么如何规划这条路径呢?我们需要有这样一个概念:对于一个注定存在欧拉路径的图而言,抛开起点,只可能最多有一个dead end (这是注定的终点)。假设存在这样一个死胡同,那么你从任意一个点出发,在不重复走边的前提下任意走,最终状态一定会走进这个死胡同;并且此时未走过的边,必然都是一个一个封闭的环。这是因为欧拉路径里除了起点和终点,其他所有点都是入度等于出度,因此除了dead end外,你只要能从某条边进入某点,必然可以通过另一条边出去。

于是我们可以这样规划DFS算法:当你打算从start出发,随便选一个出口,就无脑递归下去,这条路径最终会走进一个dead end,我们记做path1. 然后我们考察start还有其他未被遍历的那些边。根据之前的分析,走这些边之后必然是经历一个封闭的环,也就是你无论选哪个边走下去,最终都肯定会走回来,我们将这些记做path2a, path2b, path2c... 于是我们只要这样规划路径:start + ... + path2c + path2b + path2a + path1,也就是将唯一会走入死胡同的路径放在最后一个即可,这样就构造一条从start开始的欧拉路径。

那么如果全图没有dead end呢?那么相当于没有path1,你从start的任何一个边出去,都一定会再转回来。上述的算法依然有效。