图--有向无负权回路的单源最短路径 DAG 算法导论p365
来源:互联网 发布:天猫美工外包价格 编辑:程序博客网 时间:2024/06/06 08:33
DAG_SHORTEST_PATHS该算法是对某加权的有向无回路图(即DAG图),特指的是无负权回路图,即可是带负权边的图或是带正值的回路图。时间是(V+E)
实现步骤是:
1、建立有向邻接表
2、然后DAG_SHORTEST_PATHS函数:该函数主要是对图dag
1、进行拓扑排序(即是1、对图进行深搜 2、按深搜完成时间有大到小排列 (这是利用point向量对 图进行排序,所以各点在AdjList向量中的位置不变)
2、然后按拓扑排序的顺序只对各边松弛一次就即可
3、输出
#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX 99999999//表示无穷大typedef struct node{int adjvex;//连接点int weight;//边的权值struct node *next;}EdgeNode;typedef struct vnode{char str[20];int pre;//该点深搜时的前驱int dis;//节点发现时间int fish;//记录该顶点完成时间即该点标为黑色的时间int color;//1代表白色表示该点尚未发现 2代表灰色现已发现 3代表黑色表示与它邻接的边已发现int distance;//源点到该的距离EdgeNode *firstedge;}VertexNode;VertexNode AdjList[10001];typedef struct {int fish;//完成时间int id;// 指示拓扑排序后 AdjList向量中分量的位置}dpoint;dpoint point[10001];int time;//时间计数器void CREAT_ADJLIST_GRAPH(int n,int e) //节点及边的录入 以及建立邻接表{ int i,j,s,d,find,weight; char str1[20],str2[20];EdgeNode *p;printf("请输入一次输入所有字符节点 且第一个输入的点默认为源节点\n");for(i=0;i<n;i++){scanf("%s ",&AdjList[i].str);AdjList[i].firstedge=NULL;}printf("请输入各条边\n");for(i=1;i<=e;i++)//建立邻接表 由于是无向图则要申请两个节点p和q{ find=0;scanf("%s %s %d",&str1,&str2,&weight);// u ->v &权值for(j=0;find!=2&&j<n;j++) if(strcmp(str1,AdjList[j].str)==0){s=j;find++; }else if(strcmp(str2,AdjList[j].str)==0){d=j;find++; }p=(EdgeNode*)malloc(sizeof(EdgeNode)); p->adjvex=d;p->weight=weight;p->next=AdjList[s].firstedge; AdjList[s].firstedge=p;}}void DFS_VISIT(int u)//深度搜索递归函数{ int v;EdgeNode *p;AdjList[u].color=2;//u节点已发现 标记为灰色time++;AdjList[u].dis=time;p=AdjList[u].firstedge;while(p){v=p->adjvex;if(AdjList[v].color==1){AdjList[v].pre=u; //记录v的前驱uDFS_VISIT(v);//递归深搜}p=p->next;} AdjList[u].color=3;//u节点所有邻接点均已发现,即完成任务,标记为黑色AdjList[u].fish=time=time+1;//标记完成时间 }void DFS(int n)//深度搜索{ int i;for(i=0;i<n;i++){AdjList[i].color=1;//1代表白色表示该点尚未发现AdjList[i].pre=-1;//前驱向量初始化}time=0;for(i=0;i<n;i++)if(AdjList[i].color==1)DFS_VISIT(i); }int cmp(const void *a,const void *b){return( ((dpoint*)b)->fish-((dpoint*)a)->fish );//从大到小排列}void TOPOLOGICAL_SORT(int n)//拓扑排序(其实是对point向量来拓扑排序){int i;DFS(n);//对顶点进行深度搜索 for(i=0;i<n;i++){point[i].fish=AdjList[i].fish;point[i].id=i;}qsort(point,n,sizeof(point[0]),cmp);//时间按完成时间由大到小排序}void printpath(int i)//路径输出 { if(AdjList[i].pre==-1) { printf("%s->",AdjList[i].str); return ; } else { printpath(AdjList[i].pre); printf("-%s",AdjList[i].str); } } void print(int n)//输出 { int i; //for(i=0;i<n;i++)//排序输出//printf("%7s %d",AdjList[i].str,AdjList[i].distance);//printf("\n");for(i=0;i<n;i++) if(AdjList[i].pre!=-1) { printf("%d: ",AdjList[i].distance); printpath(i); printf("\n"); } else if(i==0)printf("%d: %s\n",AdjList[i].distance,AdjList[i].str);else printf(" 无穷大 %s\n",AdjList[i].str); printf("\n");} void INITIALIZE_SINGLE_SOURCE(int n)//{int i;for(i=0;i<n;i++){ AdjList[i].pre=-1;AdjList[i].distance=MAX;}AdjList[0].distance=0;//源点 的距离初始化为0;}void RELAX(int u,int v,int weight)//松弛技术{if(AdjList[v].distance>AdjList[u].distance+weight){AdjList[v].distance=AdjList[u].distance+weight;AdjList[v].pre=u;}}void DAG_SHORTEST_PATHS(int n){int u,v,weight,i;EdgeNode *p;TOPOLOGICAL_SORT(n);//拓扑排序INITIALIZE_SINGLE_SOURCE(n);for(i=0;i<n;i++)//按完成时间由大到小依次对每条边进行松弛{u=point[i].id;//u 指示(的是拓扑中完成时间较晚的量)在AdjList向量中的位置p=AdjList[u].firstedge; while(p){v=p->adjvex;weight=p->weight;RELAX(u,v,weight);//进行松弛p=p->next;}}print(n);//输出}int main(){ freopen("1.txt","r",stdin);int n,e;printf("请输入字符节点的个数N 和边的数目E:\n");scanf("%d%d ",&n,&e);CREAT_ADJLIST_GRAPH(n,e); //节点及边的录入 以及建立邻接表DAG_SHORTEST_PATHS(n); //求DAG图单源最短路径return 0;}
- 图--有向无负权回路的单源最短路径 DAG 算法导论p365
- 算法导论-24.2-有向无回路图中的单源最短路径
- 单源最短路径算法(有向无回路)
- 单源最短路径算法(有向无回路) .
- 算法导论 单源最短路径 DAG-SHORTEST-PATHS
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路)Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- 算法导论22.4-2 有向无环图的路径数目
- 图算法--有向无环图(DAG)
- 有向无环图(DAG)的最小路径覆盖
- 有向无环图(DAG)的最小路径覆盖
- 有向无环图(DAG)的最小路径覆盖
- 有向无环图(DAG)的最小路径覆盖
- POJ3249 工作难题(DAG有向无环图的单源最短路径)
- hdu 1151 DAG图(有向无环图)的最小路径覆盖
- 图--单源最短路径 -Bellman Ford 算法(可以存在负权边的情况和负权回路)算法导论p362
- 《算法4》有向图与DAG与Kosaraju算法
- 李彦宏:我为什么不退休?
- Flex快速入门系列之三:Parsley框架简单使用(IOC以及message机制)
- VC++笔记(一)
- C++ Primer_语句杂记
- 11月26日到京
- 图--有向无负权回路的单源最短路径 DAG 算法导论p365
- linux中atexit的用法
- Flex快速入门系列之四:idea创建项目以及远程对象访问
- YAML的Java实现——JYAML基本原理与示例(1)导出数据为YAML格式文件
- 指针详解
- arm汇编 EXPORT 或 GLOBAL
- Filter
- POJ 1004 解题报告 Financial Management
- 国人必备常识-收藏