欧拉通路 java,欧拉回路

基本概念及定理

1. 欧拉通路、欧拉回路、欧拉图

无向图:

1)

设G是连通无向图,则称经过G的每条边一次并且仅一次的路径为欧拉通路;

2)

如果欧拉通路是回路(起点和终点是同一个顶点),则称此回路为欧拉回路(Euler circuit);

3) 具有欧拉回路的无向图G称为欧拉图(Euler

graph)。

有向图:

1) 设D是有向图,D的基图连通,则称经过D的每条边一次并且仅一次的有向路径为有向

欧拉通路;

2)

如果有向欧拉通路是有向回路,则称此有向回路为有向欧拉回路(directed Euler circuit);

3)

具有有向欧拉回路的有向图D称为有向欧拉图(directed Euler graph)。

请思考图5.1中的无向图及有向图是否为欧拉图或有向欧拉图。

20180926043457252330.jpg

图5.1 欧拉回路及有向欧拉回路

2. 定理及推论

欧拉通路和欧拉回路的判定是很简单的,请看下面的定理及推论。

定理5.1

无向图G存在欧拉通路的充要条件是:

G为连通图,并且G仅有两个奇度结点(度数为奇数的顶点)或者无奇度结点。

推论5.1:

1) 当G是仅有两个奇度结点的连通图时,G的欧拉通路必以此两个结点为端点。

2)

当G是无奇度结点的连通图时,G必有欧拉回路。

3) G为欧拉图(存在欧拉回路)的充分必要条件是G为无奇度结点的连通图。

EXP图5.1(a)所示的无向图,存在两个奇度顶点v2和v5,所以存在欧拉通路,且欧拉通路必

以这两个顶点为起始顶点和终止顶点;该无向图不存在欧拉回路。图5.1(b)所示的无向图为欧拉

图。

定理5.2

有向图D存在欧拉通路的充要条件是:

D为有向图,D的基图连通,并且所有顶点的出度与入度都相等;或者除两个顶点外,其余

顶点的出度与入度都相等,而这两个顶点中一个顶点的出度与入度之差为1,另一个顶点的出度

与入度之差为-1。

推论5.2:

1)

当D除出、入度之差为1,-1的两个顶点之外,其余顶点的出度与入度都相等时,D的

有向欧拉通路必以出、入度之差为1的顶点作为始点,以出、入度之差为-1的顶点作为

终点。

2)

当D的所有顶点的出、入度都相等时,D中存在有向欧拉回路。

3)

有向图D为有向欧拉图的充分必要条件是D的基图为连通图,并且所有顶点的出、入度

都相等。

例如图5.1(c)所示的有向图,顶点v2和v4入度和出度均为1;顶点v1的出度为2、入度为1,

二者差值为1;顶

点v3的出度为1、入度为2,二者相差为-1;所以该有向图只存在有向欧拉通路,

且必须以顶点v1为始点,以顶点v3为终点。图5.1(d)所示的有向图不存在有向欧拉通路。

fcecaa27ea5212ceb9bf034c36bfbf34.gif

2b65ef29a5872cc0e4771c25889edd04.gif

6a087676c59fa8b19d76e6bb55a32902.gif

1 #include

2 #include

3 #include

4 using namespacestd;5 const int MAX = 60;6 intedge[MAX][MAX];7 intdegree[MAX];8 int in[MAX],out[MAX];9 int n,type; //judge grape 类型

10 int e; //边数

11 int top; //栈底 初始化为 0;

12 int stack[MAX]; //记录欧拉通路的路径

13 int vis[MAX]; //是否已经访问;

14 void DFS(int cur) //连通性的判断 是否完全访问掉

15 {16 inti ;17 for(i = 0; i

27

28 //判断是否存在欧拉回路:29 //无向图中: 连通图且所有顶点度数为偶数30 //有向图中: 连通图且所有顶点的入度等于出度

31 booljudge()32 {33 memset(vis,0,sizeof(vis)); //访问初始化

34 DFS(0);35 for(int i =0; i

40 if(type) //有向图

41 {42 for (int i=0; i

49 {50 for(int i =0; i

61 void DFS_first(int cur ,intpos)62 {63 inti,a,b;64 stack[top++] =cur;65 for(i = pos;i

77 {78 b = stack[--top];79 a = stack[--top];80 edge[a][b] = 1;81 out[a]++;82 in[b]++;83 DFS_first(a,b+1);84 }85 }86 //无向图的欧拉回路, cur 点, 从 pos 点开始搜

87 void DFS_two(int cur,intpos)88 {89 inti,a,b;90 stack[top++] =cur;91 for(i = pos;i

104 {105 b = stack[--top];106 a = stack[--top];107 edge[a][b] = 1;108 edge[b][a] = 1;109 degree[a]++;110 degree[b]++;111 DFS_two(a,b+1);112 }113

114 }115 intmain()116 {117 printf("0, 无向图 1, 有向图 :");118 scanf("%d", &type);119 printf("输入顶点个数:");120 scanf("%d",&n);121 memset(edge,0,sizeof(edge));122 memset(degree,0,sizeof(degree)); //无向图的度数

123 memset(in,0,sizeof(in)); //有向图的入度

124 memset(out,0,sizeof(out)); //有向图的出度

125

126 while(true)127 {128 int a,b; //边集

129 scanf("%d %d",&a,&b);130 if(!(a||b)) //0 0 break

131 {132 break;133 }134 edge[a][b] = 1;135 in[b]++;136 out[a]++;137 if(!type) //如果是无向图

138 {139 edge[b][a] = 1;140 degree[a]++; //无向图的度数

141 degree[b]++;142 }143 }144 if(judge())145 {146 printf("\n一条欧拉回路:");147 if(type)148 DFS_first(0,0);149 else

150 DFS_two(0,0);151 for(int i =0; i");156 }157 putchar(‘\n‘);158 }159 else

160 {161 printf("\n不存在欧拉回路!\n");162 }163 return 0;164 }View Code

fcecaa27ea5212ceb9bf034c36bfbf34.gif

摘自《图论算法理论、实现及应用-王桂平》

原文:http://www.cnblogs.com/locojyw/p/3724562.html

package hamierton; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Random; public class EularCircuit { public EularCircuit() { } public static void main(String[] args) { // System.out.println("please input n:"); // BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = 4; try { // n = Integer.parseInt(br.readLine()); } catch (Exception ex) { return; } try { Graph g = new Graph(n); g.printg(); g.circuit(); } catch (Exception e) { System.out.println(e.toString()); e.printStackTrace(); return; } } } class Node { private static int count = 0; private String name; private ArrayList adjacencyList; private boolean visited =false; public Node() { name = "node " + count; adjacencyList = new ArrayList(); } public Node(String name) { this.name = name; adjacencyList = new ArrayList(); } public boolean isAllVisited() { for (int i = 0; i < adjacencyList.size(); i++) { SNode sn = (SNode) adjacencyList.get(i); if (sn.visited == false) { return false; } } return true; } public boolean isvisited(){ return visited; } public void setvisited(){ visited = true; } public int getAdjacencyCount() { return adjacencyList.size(); } public boolean contains(int i) { return this.adjacencyList.contains(new SNode(i)); } public void removeAdjacencyNode(int i) { this.adjacencyList.remove(new SNode(i)); } public void addAdjacencyNode(int i) { this.adjacencyList.add(new SNode(i)); } public SNode getAdjacencyNode(int i) { return (SNode) this.adjacencyList.get(i); } public SNode getAdjacencyNodeEX(int i_ref) { for (int i = 0; i < this.getAdjacencyCount(); i++) { if (getAdjacencyNode(i).index == i_ref) { return getAdjacencyNode(i); } } return null; } public String toString() { return this.name; } } class SNode { public boolean visited = false; public int index = 0; public SNode(int index) { this.index = index; } public boolean equals(Object o) { if (((SNode) o).index == this.index) { return true; } return false; } public String toString() { return "adjacency " + index; } } class Graph { private ArrayList nodeList; private ArrayList path; private int count; public Graph(int n) throws Exception { this.count = n; nodeList = new ArrayList(count); ginit(); } public void circuit() { path = new ArrayList(); int top = 0; int k = 0; path.add(new Integer(0)); while (true) { int i, j; i = top; ArrayList path1 = new ArrayList(); path1.add(new Integer(top)); while (true) { Node node = (Node) nodeList.get(i); for (j = 0; j = path.size()) { break; } top = ((Integer) path.get(k)).intValue(); } for (int z = 0; z < path.size(); z++) { System.out.print(path.get(z).toString() + " "); } } private void ginit() { int i; for (i = 0; i < 4; i++) { nodeList.add(new Node("node" + i)); } ((Node)nodeList.get(0)).addAdjacencyNode(3); ((Node)nodeList.get(1)).addAdjacencyNode(0); ((Node)nodeList.get(2)).addAdjacencyNode(1); ((Node)nodeList.get(3)).addAdjacencyNode(2); // ((Node)nodeList.get(0)).addAdjacencyNode(3); // ((Node)nodeList.get(1)).addAdjacencyNode(0); // ((Node)nodeList.get(2)).addAdjacencyNode(1); // ((Node)nodeList.get(3)).addAdjacencyNode(2); // for (i = 0; i < n; i++) { // nodeList.add(new Node("node" + i)); // } // ArrayList linked = new ArrayList(); // linked.add(new Integer(0)); // Random rand = new Random(); // // for (i = 1; i = (linked.size() - 1 > 6 ? 6 // : linked.size() - 1)) { // continue; // } else { // i--; // } // node.addAdjacencyNode(randint); // Node randnode = (Node) nodeList.get(randint); // randnode.addAdjacencyNode(top); // break; // } // } // } // // for (i = 0; i < this.count - 1; i++) { // Node node = (Node) nodeList.get(i); // if (node.getAdjacencyCount() % 2 != 0) { // int j = 0; // for (j = i + 1; j < this.count; j++) { // Node nn = (Node) nodeList.get(j); // if (nn.getAdjacencyCount() % 2 != 0) { // if (node.contains(j)) { // // if (nn.getAdjacencyCount() != 1 // && node.getAdjacencyCount() != 1) { // node.removeAdjacencyNode(j); // nn.removeAdjacencyNode(i); // break; // } else { // continue; // } // } else { // // node.addAdjacencyNode(j); // nn.addAdjacencyNode(i); // break; // } // } // } // // if (j == this.count) { // int k; // Node nk = null; // for (k = i + 1; k < this.count; k++) { // // nk = (Node) nodeList.get(k); // if (nk.getAdjacencyCount() % 2 != 0) { // break; // } // } // int kk = k; // for (k = 0; k < i; k++) { // Node n1 = (Node) nodeList.get(k); // if (!n1.contains(kk) && !n1.contains(i)) { // n1.addAdjacencyNode(kk); // nk.addAdjacencyNode(k); // n1.addAdjacencyNode(i); // node.addAdjacencyNode(k); // break; // } // } // boolean retry = false; // // if (k == i) { // int vv; // for (vv = 0; vv < this.count; vv++) { // Node vn = (Node) nodeList.get(vv); // if (!vn.contains(i) && i != vv) { // vn.addAdjacencyNode(i); // node.addAdjacencyNode(vv); // retry = true; // break; // } // } // if (vv == count) { // for (vv = 0; vv 1) { // vnn.removeAdjacencyNode(i); // node.removeAdjacencyNode(vv); // retry = true; // break; // } // } // } // } // if (retry) { // i = -1; // } // } // } // // } // return this.isEularG(); } public boolean isEularG() { boolean isEular = true; for (int i = 0; i < this.count; i++) { Node n = (Node) nodeList.get(i); if (n.getAdjacencyCount() % 2 != 0) { isEular = false; break; } } return isEular; } public void printg() { for (int i = 0; i < this.count; i++) { Node n = (Node) nodeList.get(i); System.out.print(n.toString() + " "); for (int j = 0; j < n.getAdjacencyCount(); j++) { System.out.print(n.getAdjacencyNode(j).toString() + " "); } System.out.println(); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值