寒假的第二周,弥补了一下图论算法。在这里做一下总结,主要针对近期学到的一些建模技巧,同时也非常感谢有朋友能够给出图论算法相关的精彩讲解或者知识链接。
算法总结:
欧拉回路问题:判断图是否存在欧拉回路或者欧拉通路,输出一条欧拉回路。
学习Fleury算法输出一条欧拉回路。
1 /* G是连通无向图,则称经过G的每条边一次并且仅一次的路径为 2 欧拉通路,起点和终点是同一个顶点称为欧拉回路,具有欧拉回路的 3 无向图为欧拉图。 4 依次有有向欧拉通路,有向欧拉回路,有向欧拉图 5 定理:连通图G仅有两个奇度结点或者无奇度结点 6 7 Fleury:在当前剩余图中,对于顶点v,选择和v关联的边走, 8 能不走桥就尽量不走桥 9 */ 10 #include<iostream> 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<cmath> 15 #include<algorithm> 16 #define inf 0x7fffffff 17 using namespace std; 18 const int maxn=222; 19 struct Stack 20 { 21 int top,node[maxn];///顶点的栈结构 22 }s; 23 int edge[maxn][maxn]; 24 int n,m;///顶点个数、边数 25 void dfs(int x) 26 { 27 s.top++; 28 s.node[s.top]=x; 29 for (int i=0 ;i<n ;i++) 30 { 31 if (edge[x][i]) 32 { 33 edge[x][i]=edge[i][x]=0; 34 dfs(i); 35 break; 36 } 37 } 38 } 39 void Fleury(int x) 40 { 41 s.top=0; 42 s.node[s.top]=x; 43 while (s.top >= 0 ) 44 { 45 int flag=0; 46 for (int i=0 ;i<n ;i++) 47 { 48 if (edge[s.node[s.top] ][i]) 49 { 50 flag=1;break; 51 } 52 } 53 if (flag==0) 54 { 55 printf("%d ",s.node[s.top]+1); 56 s.top--; 57 } 58 else 59 { 60 s.top--; 61 dfs(s.node[s.top+1]); 62 } 63 } 64 printf("\n"); 65 } 66 int main() 67 { 68 int a,b; 69 scanf("%d%d",&n,&m); 70 memset(edge,0,sizeof(edge)); 71 for (int i=0 ;i<m ;i++) 72 { 73 scanf("%d%d",&a,&b); 74 edge[a-1][b-1]=edge[b-1][a-1]=1; 75 } 76 int cnt=0,num=0,start=0; 77 for (int i=0 ;i<n ;i++) 78 { 79 cnt=0; 80 for (int j=0 ;j<n ;j++) cnt += edge[i][j]; 81 if (cnt%2) 82 { 83 start=i ;num++ ; 84 } 85 } 86 if (num==0 || num==2) Fleury(start); 87 else printf("No Euler path\n"); 88 return 0; 89 }
拓扑排序:和有向无环图的问题相关。
1 ///toposort 栈实现 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 #include<algorithm> 8 #include<stack> 9 using namespace std; 10 const int maxn=100+10; 11 12 int n; 13 int in[maxn],degree[maxn]; 14 int an[maxn]; 15 int g[maxn][maxn]; 16 int toposort() 17 { 18 memset(in,0,sizeof(in)); 19 memcpy(in,degree,sizeof(degree)); 20 stack<int> S; 21 while (!S.empty()) S.pop() ; 22 for (int i=0 ;i<n ;i++) if (in[i]==0) S.push(i); 23 int j=0; 24 int flag=0; 25 while (!S.empty()) 26 { 27 if (S.size()>1) flag=1;///有多种排序方式,序列不确定 28 int k=S.top() ;S.pop() ; 29 an[j++]=k;///记录出栈的数字 30 for (int i=0 ;i<n ;i++) 31 { 32 if (g[k][i]) 33 { 34 if (--in[i]) S.push(i);///入度为0的结点入栈 35 } 36 } 37 } 38 if (j!=n) return 1;///不能拓扑排序,有环 39 if (flag) return 2; 40 return 3;///序列唯一 41 } 42 43 int main() 44 { 45 return 0; 46 }