• SPFA和FLOYD算法如何打印路径


    早晨碰到了一题挺裸的最短路问题需要打印路径:vijos1635

    1.首先说说spfa的方法:

    其实自己之前打的最多的spfa是在网格上的那种,也就是二维的

    一维的需要邻接表+queue

    以及对于queue的操作,自己也是醉了

    这里贴一个模板(不含打印路径):

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<iostream>
    using namespace std;
    const int maxn=10100;
    int n,m,k,t,x,y,s,ans=0;
    long long tot=0;
    struct edge{
    	int from,to,w,next;
    }e[10100000];
    int head[maxn],dist[maxn];
    bool vis[maxn];
    void add(int x,int y,int z){//邻接表
    	e[tot].from=x;
    	e[tot].to=y;
    	e[tot].w=z;
    	e[tot].next=head[x];
    	head[x]=tot++;
    }
    void spfa(int s){
    	queue<int>q;
    	memset(dist,63,sizeof(dist));
    	memset(vis,false,sizeof(vis));//感觉这里的赋值和二维的略有区别,这里是初始值false
    	q.push(s);
    	dist[s]=0;
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		vis[u]=false;②
    		for(int i=head[u];i!=-1;i=e[i].next){
    			int v=e[i].to;
    			if(dist[v]>dist[u]+e[i].w){
    				dist[v]=dist[u]+e[i].w;
    				if(!vis[v]){         //如果已经入队,或是初始值①
    					vis[v]=true;
    					q.push(v);
    				}
    			}
    		}
    	}
    }
    int main(){
    	scanf("%d",&n);
    	memset(head,-1,sizeof(head));//记得head赋值为-1
    	for(int i=1;i<=n;i++)
    	   for(int j=1;j<=n;j++){
    	   	  scanf("%d",&s);
    	   	  if(s!=0){
    	   	  	  add(i,j,s);
    	   	  }
    	   }
        spfa(1);
        printf("%d",dist[n]);
        return 0;
    }
    

     好好感受一下①和②

    对于spfa打印路径问题:

    这里就需要用上指针的思想,去找n的前驱

    所以如果dist有更新值,那么就记录下,但是这里要理解,

    你记录的并不是根据这条路的路径顺序记的

    说白了就是,f[1]并不是第一条路径

    而是让v->u,这才是f应该做的

       if(dist[v]>dist[u]+e[i].w){
    	dist[v]=dist[u]+e[i].w;
    f[v]=u;//在更新值的后面加上这个
    if(!vis[v]){ vis[v]=true; q.push(v); }
    }

     以及调用一个递归函数寻找前驱:

    void printpath(int k){
        if(k!=0){
        	printpath(f[k]);
        	printf("%d ",k);
        }
    }
    

    2.FLOYD算法:

    初始化 f[i][j]=j;

    之后也是在更新值后面加上一条语句:

    k=1-n

    i=1-n

    j=1-n

      if(..>..)

        dist[i][j]=dist[i][k]+dist[k][j];

        f[i][j]=f[i][k];

    比如要打印v,w的路径:
                k=P[v][w];                /* 获得第一个路径顶点下标 */
                printf(" path: %d",v);    /* 打印源点 */
                while(k!=w)                /* 如果路径顶点下标不是终点 */
                {
                    printf(" -> %d",k);    /* 打印路径顶点 */
                    k=P[k][w];            /* 获得下一个路径顶点下标 */
                }
                printf(" -> %d
    ",w);    /* 打印终点 */
    

      

  • 相关阅读:
    C语言成长学习题(八)
    C语言成长学习题(七)
    C语言成长学习题(六)
    C语言成长学习题(五)
    Linux下zookeeper下载与安装教程
    Linux下mongoDB下载与安装
    并发容器之阻塞队列DelayQueue的使用案例及源码分析
    原子操作CAS-最小的线程安全
    ThreadLocal定义、使用案例及源码分析
    mac上使用git命令上传项目工程源码至Github/gitee
  • 原文地址:https://www.cnblogs.com/polebug/p/3907452.html
Copyright © 2020-2023  润新知