有一条名为Pregel的河流经过Konigsberg城。城中有7座桥。把河中的两个岛与河岸连接起来。当地居民热衷于一个难题:是否存在于一条路线,可以不重复地走遍7座桥。这就是著名的七桥问题。它由大数学家欧拉首先提出,并给出了完美的解答。
欧拉首先把图中的七桥问题用图论的语言改写成图,则问题变成了:能否从无向图中的一个结点出发走到一条道路,每条边恰好经过一次。这样的路线称为欧拉道路。也可以形象的称为一笔画。
在欧拉道路中,进和出是对应的-除了起点和终点外,其他点的进出次数应该相等。换句话说,除了起点和终点外,其他点的度数(degree)应该是偶数。很可惜,在七桥问题中,所有4个点的度数均是奇数(这样的点也称奇点),因此不可能存在欧拉回路。上述条件也是充分条件-如果一个无向图是连通的,且最多只有两个奇点,则一定存在欧拉回路。如果有两个奇点,则必须从其中一个奇点出发,另一个奇点终止。如果奇点不存在,则可以从任意点出发,最终一定会回到该点(称为欧拉回路)。
用类似的推理方式可以得到有向图的结论:最多只能有两个点的入度不等于出度,而且必须是其中一个点的出度恰好比入度大1(把它作为其起点),另一个的入度比出度大1(把它作为终点)。当然,还有一个前提条件:在忽略边的方向后,图必须是连通的。
总结一下。
欧拉路径:
有向图:最多只能有两个点的入度不等于出度,而且必须是其中一个点的出度恰好比入度大1,另一个的入度比出度大1,把它作为终点,当然在忽略边的方向后,图必须是连通的。
无向图:有两个奇点,从一个奇点出发,到达另一个奇点
欧拉回路:
有向图存在欧拉回路的充要条件:所有顶点的入度等于出度且该图是连通图。
无向图存在欧拉回路的充要条件:当且仅当该图所有顶点度数都为偶数,且该图是连通图。
首先给出存储结构:
int n, G[maxn][maxn];
bool vis[maxn][maxn];
有向图的欧拉道路:
如果需要打印的是欧拉道路,在主程序中调用时,参数必须是道路的起点。另外,打印的顺序是逆序的,因此在真正使用这份代码时,应当把printf语句替换成一条push语句,把边压入一个栈内。代码改为无向图的话,把vis[u][v]=true 改为 vis[u][v]=vis[v][u]=1即可。
void euler(int u)
{
for(int v = 1; v <= n; v++)
if(G[u][v] && !vis[u][v])
{
vis[u][v] = true; //有向图去掉vis[v][u]
euler(v);
printf("%d %d\n",u, v);
}
}