• 最短路径(弗洛伊德算法 迪杰斯特拉算法 贝尔曼-福特算法)


    弗洛伊德算法:

    弗洛伊德算法核心代码:

    for(int k=0;k<n;k++)
    {
    	for(int i=0;i<n;i++)
    	{
    		for(int j=0;j<n;j++)
    		{
    			dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    		}
    	}
    }	
    

    上述代码只有五行,时间复杂度是N的三次方。本算法最大的优点就是代码简洁。在对时间复杂度要求不高的情况下,可以通过此算法找到任意两点间或者指定一点到另一点的最小距离。
    思路:
    寻找两点间的最小距离,我们可以通过引入中间点来寻找最短距离。例如:我们需要寻找i和j两点间的最小距离,那么我们可以引入中间点k,通过判断i到k再到j的距离是否小于此时i到j的距离,如果是,则更新i到j点的距离。此算法运用了动态规划的思想。
    具体代码如下:

    #include <stdio.h>
    int dis[105][105],n,q,a,b,c,Inf=1e9;
    int min(int x,int y)
    {
    	return x<y?x:y;
    }
    int main()
    {
    	scanf("%d%d",&n,&q);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			if(i!=j)
    				dis[i][j]=Inf;
    		}
    	}
    	for(int i=0;i<q;i++)
    	{
    		scanf("%d%d%d",&a,&b,&c);
    		dis[a][b]=min(dis[a][b],c);
    	}
    	for(int k=1;k<=n;k++)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			for(int j=1;j<=n;j++)
    			{
    				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);//防止重边
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    				printf("%d ",dis[i][j]);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    

    贝尔曼-福特算法

    核心代码:

    for(int i=0;i<n-1;i++)
    {
    	for(int j=0;j<m;j++)
    	{
    		dis[v[j]]=min(dis[v[j]],dis[u[j]]+w[j]);
    	}
    }
    

    贝尔曼-福特算法用来寻找指定点到其他点的最短距离,并且可以解决迪杰斯特拉算法不能解决的负权值问题。缺点是时间复杂度较高。
    上述代码表明,我们有m条边。而我们的目的就是通过选择不同的边来寻找两点间的最短距离。外循环一共循环了n-1次,表示两点间最多有n-1条边。内循环枚举每一条边,通过比较来寻找最多通过i+1条边时,两点间的最短距离。而我们发现,很多情况下,不必循环n-1次,某些点便已经找到了最短距离,此后用这些点去更新所连接的点,不会产生任何影响。这就启发我们,**每次只处理最短路数值发生变化的点,因为只有发生变化的点,与其有临边的点的最短路才有可能变化。**所以我们采用队列优化的方式,来实现贝尔曼-福特算法。
    代码如下:

    #include <stdio.h>
    int n,m,dis[1005],u[1005],w[1005],v[1005],first[1005],next[1005],head,tail,que[10000],temp,b[1005]; //为了减少复杂度,我们采用邻接表储存图
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	{
    		next[i]=-1;
    		first[i]=-1;
    		dis[i]=1e9;
    	}
    	dis[1]=0;
    	for(int i=0;i<n;i++)
    	{
    		scanf("%d%d%d",&u[i],&v[i],&w[i]);
    		next[i]=first[u[i]];      //next[i]储存的是以i号路的上一条路的编号 
    		first[u[i]]=i;           //first[u[i]]储存的是以u[i]为顶点的第一条路的编号 
    	}
    	head=0;
    	tail=1;
    	que[head]=1;
    	temp=first[que[head]];
    	while(tail>head)
    	{
    		while(temp!=-1)
    		{
    			if(dis[v[temp]]>dis[u[temp]]+w[temp])
    			{
    				if(!b[v[temp]])
    				{
    					b[v[temp]]=1;
    					que[tail++]=v[temp];
    				}
    				dis[v[temp]]=dis[u[temp]]+w[temp];
    			}
    			temp=next[temp];
    		 } 
    		 book[que[head]]=0;
    		 head++;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		printf("%d ",dis[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    vue 下拉框单选、多选以及默认值
    python 查询每周最后一个工作日
    微信开发
    win7 实用
    A Mixed Flash Translation Layer Structure for SLC-MLC Combined Flash Memory System
    暑假--升级攻击家庭wifi
    A New 3-bit Programming Algorithm using SLC-to-TLC Migration for 8MBs High Performance TLC NAND Flash Memory
    FTL方面综述
    Linux 脚本
    FTL-SLC&MTC&TLC
  • 原文地址:https://www.cnblogs.com/fxzemmm/p/14847987.html
Copyright © 2020-2023  润新知