• 算法结点图的多源点最短路问题和传递闭包之FloydWarshall算法 By ACReaper


    最近一直在研究算法结点之类的问题,上午正好有机会和大家共享一下.

        我们道知求图的最短路有Dijkstra应用于无负权的算法,也有应用于有负权的Bellman0-Ford算法,但是当源点有多个呢?难道我们要用调n次的Dijkstra算法?有没有其它的算法呢?这是当然的,Floyd-Warshall就是用来处理这个问题的,或许有学过的人会说这个算法的率效太低,为O(n^3)但是,当摊销到每一条路上时,其率效为O(V)还是很高的,很适用的一个算法。

        

        Floyd-Warshall算法是基于最短路的子路也一定是最短路这一最优子结构,加上动态规划思想来实现的,对于图中,我们假设dij(k)示表从结点Vi到结点Vj的最短路,k为其上标,示表在dij这条最短路的中间结点是属于{1,2,3....k}这个合集的,所以我们假设有结点P,合集S为{1,....k},合集Q为S-{p},那么对于dij(k)这条最短路,结点k要么在其上,要么不在,所以我们有

        Dij(k) = min(Dij(k-1),Dik(k-1) + Dkj(k - 1))。

        接着我们用递推来少减重复的算运,算法如下:

        

        每日一道理
    这浓浓的母爱使我深深地认识到:即使你是一只矫健的雄鹰,也永远飞不出母爱的长空;即使你是一条扬帆行驶的快船,也永远驶不出母爱的长河!在人生的路上不管我们已走过多远,还要走多远,我们都要经过母亲精心营造的那座桥!
    #include <stdio.h>
    //和算法导论中Floyd-Warshall算法,在图的存储中采取邻接矩阵不同,我们采取邻接链表来
    //存图,并且实现该算法
    
    #define MAXN 1000 
    #define INF 1 << 30
    int first[MAXN + 1];
    int next[MAXN + 1];
    int d[MAXN + 1][MAXN + 1];
    int c[MAXN + 1][MAXN + 1];
    int u[MAXN + 1];
    int v[MAXN + 1];
    int w[MAXN + 1];
    int n,m;
    int main(){
    	
    	while(scanf("%d%d",&n,&m) != EOF){
    		for(int i = 1; i <= n; i++){//Init,0代表NULL 
    			first[i] = 0;
    		}
    		for(int i = 1; i <= m; i++){
    			next[i] = 0;
    		}
    		
    		for(int e = 1; e <= m; e++){//构建邻接链表 
    			scanf("%d%d%d",u + e, v + e, w + e);
    			next[e] = first[u[e]];
    			first[u[e]] = e; 
    		}
    		
    		//动态规划初始化 
    		for(int i = 1; i <= n; i++){
    			for(int j = 1; j <= n; j++){
    				d[i][j] = INF;
    				c[i][j] = i == j?1 : 0;
    			}
    			d[i][i] = 0;
    			for(int e = first[i]; e != 0; e = next[e]){
    				d[i][v[e]] = w[e];
    				c[i][v[e]] = 1;
    			}
    		} 
    		//从最底层开始递推 
    		for(int k = 1; k <= n; k++){
    			for(int i = 1; i <= n; i++){
    				for(int j = 1; j <=n ; j++){
    					if(d[i][k] != INF && d[k][j] != INF)
    						d[i][j] <?= d[i][k] + d[k][j];
    					
    					c[i][j] = c[i][j] || c[i][k] && c[k][j];
    				}
    			}
    		} 
    		
    		for(int i = 1; i <=n ; i++){
    			for(int j = 1; j <= n; j++){
    				printf("V(%d)到V(%d)的最短路存在:%d,值为:%d\n",i,j,c[i][j],d[i][j]);
    			}
    		}
    		
    	}	
    	
    	return 0;
    }

        2013 04 30

        By ACReaper

    文章结束给大家分享下程序员的一些笑话语录: AdobeFlash拖垮Windows拖垮IE!又拖垮Linux拖垮Ubuntu拖垮FirxEox!还拖垮BSD拖垮MacOS拖垮Safri!简直无所不拖!AdobeFlash滚出网路世界!不要以为市占有率高就可以持续出烂货产品!以后替代品多得是!

  • 相关阅读:
    0是字符串的终止符
    c语言中获取数组的长度写法
    c语言第一个程序
    linux下adb连接不上解决方法
    android的apk权限查看
    dumpsys netpolicy中state的含义
    查看ps和dumpsys netpolicy
    批量安装/卸载手机apk--python语言
    【转载】Think as Customer 以客户为中心的测试理念
    利用xampp进行https操作
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3052946.html
Copyright © 2020-2023  润新知