总结图论算法
Posted KID_XiaoYuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了总结图论算法相关的知识,希望对你有一定的参考价值。
1:最小生成树算法(Kruscal算法)
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> using namespace std; struct struct_edges { int bv,tv; //bv 起点 tv 终点 double w; //权值}; struct_edges edges[10100]; //边集 struct struct_a { double x;double y;}; struct_a arr_xy[101]; int point[101],n,e; //n 顶点数, e 边数(注意是无向网络) double sum; int kruscal_f1(int point[], int v) { int i = v; while(point[i] > 0) i = point[i]; return i;} bool UDlesser(struct_edges a, struct_edges b) {return a.w < b.w;} void kruscal() //只需要准备好n,e,递增的边集edges[]即可使用 { int v1,v2,i,j; for(i=0; i<n ;i++) point[i]=0; i = j = 0; while(j<n-1 && i<e) { v1 = kruscal_f1(point, edges[i].bv); v2 = kruscal_f1(point, edges[i].tv); if(v1 != v2) { sum += edges[i].w; //注意sum初始为0 point[v1]=v2; j++;} i++;}} int main() { int k,i,j;cin>>n; k=0; while(n != 0) { sum=0; k++; for(i=0; i<n ;i++) cin>>arr_xy[i].x>>arr_xy[i].y; e=0; for(i=0; i<n ;i++) //从0开始计数 for(j=i+1; j<n ;j++) //注意是无向网络 { if(i == j) continue; edges[e].bv=i; edges[e].tv=j; edges[e].w=sqrt((arr_xy[i].x-arr_xy[j].x)*(arr_xy[i].x-arr_xy[j].x)+(arr_xy[i].y-arr_xy[j].y)*(arr_xy[i].y-arr_xy[j].y)); e++;} sort(edges,edges+e,UDlesser); //得到一个递增的边集,注意是从0开始计数 kruscal(); printf("Case #%d:\n",k); //cout<<"Case #"<<k<<":"<<endl; printf("The minimal distance is: %.2f\n",sum); //输出sum cin>>n; if(n != 0) printf("\n");}}
2:最小生成树算法 (Prim算法)
#include <iostream> #include <cmath> #include <cstdio> using namespace std; double sum, arr_list[101][101], min; int i, j, k=0, n; struct struct_a { float x; float y;}; struct_a arr_xy[101]; struct struct_b {int point;float lowcost;}; struct_b closedge[101]; void prim(int n) //prim 需要准备:n顶点数arr_list[][]顶点的邻接矩阵也是从0开始计数 {int i,j,k;k=0; for(j=0; j<n ;j++) { if(j != k) { closedge[j].point = k; closedge[j].lowcost = arr_list[k][j];}} closedge[k].lowcost=0; for(i=0; i<n ;i++) { min=10000; for(j=0; j<n ;j++) { if (closedge[j].lowcost != 0 && closedge[j].lowcost < min) { k = j; min = closedge[j].lowcost;}} sum += closedge[k].lowcost; //不要改成sum+=min; sum即为所求值 closedge[k].lowcost = 0; for(j=0; j<n ;j++) { if(arr_list[k][j] < closedge[j].lowcost) { closedge[j].point = k; closedge[j].lowcost = arr_list[k][j];} } }} /* arr_list[][]= Wij 如果Vi, Vj有边 0 如果i=j 无限大 如果没有边*/ int main() { cin>>n; while(n != 0) { sum=0; k++; for(i=0; i<n ;i++) cin>>arr_xy[i].x>>arr_xy[i].y; for(i=0; i<n ;i++) for(j=0; j<n ;j++) //得到邻接矩阵arr_list[][] arr_list[i][j]=arr_list[j][i]=sqrt((arr_xy[i].x-arr_xy[j].x)*(arr_xy[i].x-arr_xy[j].x)+(arr_xy[i].y-arr_xy[j].y)*(arr_xy[i].y-arr_xy[j].y)); prim(n); cout<<"Case #"<<k<<":"<<endl; printf("The minimal distance is: %.2f\n",sum); cin>>n; if(n!=0) printf("\n"); }}
3:单源最短路径(Bellman-ford算法)
struct node { int e,v; node(int a = 0,int b = 0) : e(a), v(b) {}}; vector< vector<node> > path; int n,p,q; int dist[1000100]; /* * SPFA (Shortest Path Faster Algorithm) * Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算 * 返回值为false,说明队列不为空,存在负权环 */ bool SPFA() { int i,j,k,now,l;node next;bitset <1000100> vis; queue< int > SQ;memset(dist,-1,sizeof(dist)); SQ.push(1);vis[1] = true;dist[1] = 0; for (i=0;i<=n;i++) { l = SQ.size(); if (l == 0) break; while (l--) { now = SQ.front();SQ.pop();vis[now] = false; for (j=path[now].size()-1;j>=0;j--) { next = path[now][j]; if (dist[next.e]==-1 || dist[next.e] > dist[now]+next.v) { dist[next.e] = dist[now]+next.v; if(!vis[next.e]) { SQ.push(next.e);vis[next.e] = true;}}}}} return SQ.empty();}
4:单源最短路径(Dijkstra算法)
int matrix[200][200],n; //matrix[][], 30000表示无限大,即无边.否则为有边,其值为边的权值 void Dijkstra(int x,int y) //起点Vx 终点Vy {int i,j,k,path[40000],mark[40000]; int min,dist[40000]; for(i=1;i<=n;i++) { mark[i] = 0;dist[i] = matrix[x][i]; path[i] = x;} mark[x] = 1; do { min=30000; k=0; for(i=1;i<=n;i++) if(mark[i]==0 && dist[i]<min) { min = dist[i]; k = i;} if(k) { mark[k] = 1; for(i=1;i<=n;i++) if(matrix[k][i]<30000 && min+matrix[k][i]<dist[i]) { dist[i] = min + matrix[k][i]; path[i] = k; }} }while(k); cout<<dist[y]<<endl; //dist[y] 的值就是从Vx 到 Vy 的最短路径值 //如果希望得到路径,加入如下代码: do {cout<<k<<"<--";k = path[k]; }while(k!=x); cout<<x<<endl;}
5:全源最短路径(Folyd算法)
void Floyd() { int i,j,k; for(k=0;k<vertex_number;k++) { for(i=0;i<vertex_number;i++) { for(j=0;j<vertex_number;j++) { if((graph[i][k]==-1) || (graph[k][j]==-1)) continue; if((graph[i][j]==-1) || (graph[i][j] > graph[i][k]+graph[k][j])) { graph[i][j] = graph[i][k]+graph[k][j]; /*最短路径值*/ path[i][j] = k; /*最短路径*/ } } } } }
6:拓扑排序
/**** **** **** **** **** **** * Function Name : 拓扑排序 **** **** **** **** **** ****/ //degree[] 每个结点的入度 //f[] 每个结点所在的层 void Toplogical_sort() { int i,j;bool p=true;top=0; while(p) { p=false; top++; for(i=1;i<=n;i++) if(degree[i]==0) {p=true; f[i]=top; } for(i=1;i<=n;i++) if(f[i]==top) { for(j=1;j<=n;j++) if(map[i][j]) degree[j]--; degree[i]=-1; } } top--; }
以上是关于总结图论算法的主要内容,如果未能解决你的问题,请参考以下文章