1. 程式人生 > >Fleury演算法求歐拉回路(二)

Fleury演算法求歐拉回路(二)

  上一篇文章當中介紹了Fleury演算法是什麼以及演算法流程,本篇文章將介紹如何用程式碼來實現求解歐拉回路。廢話不多說先來三個例子,這三個例子分別是兩個尤拉圖和一個非尤拉圖。

  非尤拉圖:

圖 1  


  尤拉圖一:

圖 2 (此圖來自《離散數學教程》p135)


  尤拉圖二:(這是一個七個點的圖,每一個點都是6條邊)

圖 3


  現在我們來開始編碼,首先,建立一個二維陣列來儲存圖,然後是輸入點的個數和邊的個數,以及哪兩個點有邊。以下是程式碼片段:

#include<stdio.h>

int eulerGraph[1000][1000] = {{0}};//用來儲存圖,全域性的二維陣列

int V,E;//邊以及點的個數
  
printf("please input the number of V (no more than 1000): \n");
scanf("%d",&V);
printf("please input the number of E : \n");
scanf("%d",&E);
printf("please input E : \n");
int i,j;
//Init eulerGraph
	
for(i = 0; i < V; i++) {
	for(j = 0; j < V; j++) {
		eulerGraph[i][j] = 0;
	}
}
int m,n;
//create graph
for (i = 0; i < E; i++) {
	scanf("%d %d",&m,&n);
	if ((m >= V) || (n >= V)) {
		printf("cannot more than V\n");
		return 1;
	}
	eulerGraph[m][n] = eulerGraph[n][m] = 1;
}

列印你的點,看看是否輸入正確:
	for(i = 0; i < V; i++) {
		for(j = 0; j < V; j++) {
			printf("%d ",eulerGraph[i][j]);
		}
		printf("\n");
	}
然後,判斷是否為尤拉圖:
if (!isEulerGraph()) {
		
		printf("the graph is not euler graph!\n");
		return 1;
	}
isEulerGraph()函式:
int  isEulerGraph() {
	int i,j;
	int count = 0;
	for (i = 0; i < V; i++) {
		for (j = 0; j < V; j++) {
			if (1 == eulerGraph[i][j]) 
				count++;
		}
		if (0 != count % 2 )
			return 0;
		count = 0;
	}
	return 1;
}

接下來就是Fleury演算法:
fleury();
void fleury () {
	//set a start ,v0
	int temp[1000] ={0};
	printf("%d -> ",temp[0]);
	int i = 0;
	int j = 0;
	int top = 0;
	int bridge = 1;
	int tmp;
	for (i = 0; i < E; i++) {//Traversal all E
		for (j = 0; j < V; j++) {
			if(1 == eulerGraph[temp[top]][j]) {
				eulerGraph[temp[top]][j] = eulerGraph[j][temp[top]] = 0;
				//if the E is bridge,take a signal in this E,else delete this E
				if(isBridge(temp[top],j)) {
					tmp = j;		
					eulerGraph[temp[top]][j] = eulerGraph[j][temp[top]] = 1;
				}
				else {
					top++;
					temp[top] = j;
					bridge = 0;
					printf("%d -> ",j);
					break;
				}
					
			}
		}
		//if bridge == 1, no another E in this V that the E is not bridge
		if (bridge) {
			eulerGraph[temp[top]][tmp] = eulerGraph[tmp][temp[top]] = 0;
			top++;
			temp[top] = tmp;
			printf("%d -> ",tmp);
		}
		bridge = 1;
	}
//	for (i = 0; i < (E - 1); i++) {
//		printf("%d -> ",temp[i]);
//	}
//	printf ("%d",temp[E-1]);
}

呼叫的isBridge函式:

首先,建立一個數組用來儲存要判斷的Vi能夠到達的點,只要數組裡面的點未遍歷完那麼就把這些點能夠到達的點,並且在陣列中還未遍歷過加進來。以下是原始碼:

int isBridge (int m, int k) {
	int temp[1000] = {-1};
	int i = 0;
	for (i = 0; i < 1000; i++) {
		temp[i] = -1;
	}
	int tmp = 0;
	temp[tmp] = m;
	int n = 0;
	//判斷從m->k是否還有其他路徑
	for (tmp = 0; temp[tmp] != -1; tmp++ ) {		
		for (i = 0; i < V; i++) {
			
			if (eulerGraph[temp[tmp]][i] == 1 && i == k) {
				return 0;//because is exist another way to k,so m->k is not bridge  
			}
			if (eulerGraph[temp[tmp]][i] == 1 && isExist(temp,i) == 0) {//將當前的點有邊的點,前面沒有到過的點加入到陣列當中
				n++;
				temp[n] = i;//take new V into temp array
			}
		}
	}
	//not found k,so m->k is bridge
	return 1;
}

下面是判斷之前是否已經遍歷過這個點了,陣列中是否存在
int isExist (int *temp,int m) {
	int i = 0;
	while (temp[i] != -1) {
		if (temp[i] == m)
			return 1;
		i++;
	}
	return 0;
}
以下是測試結果和全部的原始碼:

測試非尤拉圖:





測試尤拉圖一:


 

測試尤拉圖二:(本人有點懶,所以就不打算使用手動輸入的方式嘍,採用輸入重定向的方式來進行輸入,大家平時測試的時候也可以這樣做,畢竟比較方便一點)

輸入:

7
21
0 1
0 2
0 3
0 4
0 5
0 6
1 2
1 3
1 4
1 5
1 6
2 3
2 4
2 5
2 6
3 4
3 5
3 6
4 5
4 6
5 6

輸出:


以上就是我對於Fleury演算法的理解,如果覺得還可以,請點個贊或者在下方評論,以下是我的原始碼:

/*************************************************************************
    > File Name: Fleury.c
    > Author: pengjinghui
    > Mail: [email protected] 
    > Created Time: 2015年09月24日 星期四 21時56分27秒
 ************************************************************************/

#include<stdio.h>

int eulerGraph[1000][1000] = {{0}};//用來儲存圖,全域性的二維陣列

int V,E;//邊以及點的個數

int  isEulerGraph() {
	int i,j;
	int count = 0;
	for (i = 0; i < V; i++) {
		for (j = 0; j < V; j++) {
			if (1 == eulerGraph[i][j]) 
				count++;
		}
		if (0 != count % 2 )
			return 0;
		count = 0;
	}
	return 1;
}
int isExist (int *temp,int m) {
	int i = 0;
	while (temp[i] != -1) {
		if (temp[i] == m)
			return 1;
		i++;
	}
	return 0;
}
int isBridge (int m, int k) {
	int temp[1000] = {-1};
	int i = 0;
	for (i = 0; i < 1000; i++) {
		temp[i] = -1;
	}
	int tmp = 0;
	temp[tmp] = m;
	int n = 0;
	//判斷從m->k是否還有其他路徑
	for (tmp = 0; temp[tmp] != -1; tmp++ ) {		
		for (i = 0; i < V; i++) {
			
			if (eulerGraph[temp[tmp]][i] == 1 && i == k) {
				return 0;//because is exist another way to k,so m->k is not bridge  
			}
			if (eulerGraph[temp[tmp]][i] == 1 && isExist(temp,i) == 0) {//將當前的點有邊的點,前面沒有到過的點加入到陣列當中
				n++;
				temp[n] = i;//take new V into temp array
			}
		}
	}
	//not found k,so m->k is bridge
	return 1;
}
void fleury () {
	//set a start ,v0
	int temp[1000] ={0};
	printf("%d -> ",temp[0]);
	int i = 0;
	int j = 0;
	int top = 0;
	int bridge = 1;
	int tmp;
	for (i = 0; i < E; i++) {//Traversal all E
		for (j = 0; j < V; j++) {
			if(1 == eulerGraph[temp[top]][j]) {
				eulerGraph[temp[top]][j] = eulerGraph[j][temp[top]] = 0;
				//if the E is bridge,take a signal in this E,else delete this E
				if(isBridge(temp[top],j)) {
					tmp = j;		
					eulerGraph[temp[top]][j] = eulerGraph[j][temp[top]] = 1;
				}
				else {
					top++;
					temp[top] = j;
					bridge = 0;
					printf("%d -> ",j);
					break;
				}
					
			}
		}
		//if bridge == 1, no another E in this V that the E is not bridge
		if (bridge) {
			eulerGraph[temp[top]][tmp] = eulerGraph[tmp][temp[top]] = 0;
			top++;
			temp[top] = tmp;
			printf("%d -> ",tmp);
		}
		bridge = 1;
	}
//	for (i = 0; i < (E - 1); i++) {
//		printf("%d -> ",temp[i]);
//	}
//	printf ("%d",temp[E-1]);
}

int main () {
	printf("please input the number of V (no more than 1000): \n");
	scanf("%d",&V);
	printf("please input the number of E : \n");
	scanf("%d",&E);
	printf("please input E : \n");
	int i,j;
	//Init eulerGraph
	
	for(i = 0; i < V; i++) {
		for(j = 0; j < V; j++) {
			eulerGraph[i][j] = 0;
		}
	}
	int m,n;
	//create graph
	for (i = 0; i < E; i++) {
		scanf("%d %d",&m,&n);
		if ((m >= V) || (n >= V)) {
			printf("cannot more than V\n");
			return 1;
		}
		eulerGraph[m][n] = eulerGraph[n][m] = 1;
	}
	
	for(i = 0; i < V; i++) {
		for(j = 0; j < V; j++) {
			printf("%d ",eulerGraph[i][j]);
		}
		printf("\n");
	}
	if (!isEulerGraph()) {
		
		printf("the graph is not euler graph!\n");
		return 1;
	}
	fleury();
}






相關推薦

Fleury演算法()

  上一篇文章當中介紹了Fleury演算法是什麼以及演算法流程,本篇文章將介紹如何用程式碼來實現求解歐拉回路。廢話不多說先來三個例子,這三個例子分別是兩個尤拉圖和一個非尤拉圖。   非尤拉圖: 圖 1     尤拉圖一: 圖 2 (此圖來自《離散數學教程》p135)

Fleury 演算法

基本概念: 尤拉路:通過圖中所有邊的簡單路 歐拉回路: 閉合的尤拉路 尤拉圖: 包含歐拉回路的圖 簡單的說:歐拉回路 就是經過圖(有向圖、無向圖)的每條邊一次且僅一次,回到出發點的路徑就叫歐拉回路;

jzoj5895 【NOIP2018模擬10.5】旅遊 (,性質)

題目描述 分析 一個無向圖存在歐拉回路當且僅當所有的點的度數為偶數,所以需要在每一對奇點之間連一條邊然而觀察這題這題的邊權,發現所有比某條邊小的邊之和比這條邊小。那也就是說最短路必定在最小生成樹上。這就變成了最小生成樹上的配對問題。只要保證不走重邊,結果一定是一樣的。一棵子

ACM演算法

題目描述:     歐拉回路是指不令筆離開紙面,可畫過圖中每條邊僅一次,且可以回到起點的一條迴路。現給定一個圖,問是否存在歐拉回路? 輸入:     測試輸入包含若干測試用例。每個測試用例的第1行給出兩個正整數,分別是節點數N ( 1 < N < 1000 )和

uva 10129 Play On Words(單詞)或尤通路

題目:輸入n個單詞,是否可以把這些所有單詞排成一個序列,使得每個單詞的第一個字母和上一個單詞的最後一個字母想同。 有向圖歐拉回路:1,圖連通.2,所有定點入度等於出度 有向圖尤拉通路:1,圖連通.2,僅有兩個奇度定點,其中一個入度比出度大1,另一個定點出度比入度大1 思路

poj1041 John's trip (無向圖方案)

John's trip Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5950 Accepted: 1946 Special Judge Description Little John

Fleury演算法 -無向尤圖的

背景介紹 1) 尤拉圖:存在經過圖中每條邊恰好一次並且僅一次行遍所有點的迴路 通俗來說,該回路有兩個特點: 邊:包括圖中所有邊(不重複地) 點:包括圖中所有點(可重複地) 2) 尤拉圖判斷:

弗羅萊(fleury演算法-生成演算法

弗羅萊演算法是生成歐拉回路的演算法之一,今天查看了許多資料,做一下記錄整理。 1、關於尤拉圖:               尤拉圖是由哥尼斯堡橋問題抽象而來的。哥尼斯堡橋問題是指在Pregel河兩岸就7座橋,問能否一次走完所有的橋並且不重複。問題如下:          

HDU 3018 Ant Trip (並查集連通塊數+)

http 道路 遇到 連通塊 ems ble define ant trip 註意 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3018 題目大意:有n個點,m條邊,人們希望走完所有的路,且每條道路只能走一遍。至少要將人們

路徑POJ 2230

possible 圖片 pac ans close rails AI show pair Watchcow Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 8841

定理及演算法

一:無向圖   1、定義:給定無孤立結點圖G,若存在一條路,經過圖中每條邊一次且僅一次,該條路為尤拉路, 若存在一條迴路,經過圖中每邊一次且僅一次,該回路稱為歐拉回路。 具有歐拉回路的圖稱為尤拉圖。 2、定理:無向圖G具有一條尤拉路,當且僅當G是連通的,且有0

定理及演算法

一:無向圖 1、定義:給定無孤立結點圖G,若存在一條路,經過圖中每條邊一次且僅一次,該條路為尤拉路, 若存在一條迴路,經過圖中每邊一次且僅一次,該回路稱為歐拉回路。 具有歐拉回路的圖稱為尤拉圖。

一個圖中尤圖的個數

判尤拉圖兩個條件首先聯通,其次度全部為歐度。那麼就很easy了。 題目:hdoj1878 求一個圖中尤拉圖的個數。 首先通過連通性求出各個子圖,然後求子圖中奇數度的個數cnt,cnt/2為尤拉圖的

put ++ .cn -1 bool ret 技術分享 代碼 can 思路 根據歐拉圖的概念來。 註意 點數為1; 有孤立點; 代碼實現 T掉的dfs... 1 #include<cstdio> 2 const int max

UVA 10196 Morning Walk(

ble move eve man first pre intersect sum ons Problem H Morning Walk Time Limit 3 Seconds Kamalis a Motashotaguy. He has

[] poj 1300 Door Man

linker center || 是否 connect sep cto -m vector 題目鏈接: http://poj.org/problem?id=1300 Door Man Time Limit: 1000

hdu1878(DFS+)

out sin 整數 white 偶數 ret pad bottom -m 歐拉回路 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

[模板][持續更新]路徑淺析

bits solution 算法 -1 要求 logs 鏈式前向星 namespace src Luogu P2731 騎馬修柵欄 Riding the Fences 題目背景 Farmer John每年有很多柵欄要修理。他總是騎著馬穿過每一個柵欄並修復它破損的地方。 題目

51nod 1967 路徑定向(不錯的

cnblogs 偶數 ret mes stack ostream lin .html pre http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1967 題意: 思路: 出度=入度,這

The Necklace UVA - 10054 (無向圖的

n) 兩個 logs nec get dfs lap none view The Necklace UVA - 10054 題意:每個珠子有兩個顏色,給n個珠子,問能不能連成一個項鏈,使得項鏈相鄰的珠子顏色相同。 把顏色看做點,珠子內部連一條邊,無向圖求歐拉回路。 這