zoukankan      html  css  js  c++  java
  • 图论:Floyd-多源最短路、无向图最小环

    在最短路问题中,如果我们面对的是稠密图(十分稠密的那种,比如说全连接图),计算多源最短路的时候,Floyd算法才能充分发挥它的优势,彻彻底底打败SPFA和Dijkstra

    在别的最短路问题中都不推荐使用这个算法

    我们以一道单源最短路题目介绍一下在输入数据为边表的情况下的Floyd使用情况,如果直接给了邻接矩阵的话,直接无脑求就可以了

    在这里,我们把Floyd算法的功能补全,实现了一个打印最短路径的函数并加入了求无向图的最小环的功能(经过至少两个定点,权值和最小)

    看定义:

    int n,m,s,mina=INF;
    int d[maxn][maxn],mp[maxn][maxn],p[maxn][maxn];

    n个点m条边和源点s,最小环初始化为INF

    然后d是最短路的答案数组,mp是初始地图数组,p是记录两个点之间的衔接点k,用来打印路径

    然后是初始化:

    void init()
    {
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            d[i][j]=mp[i][j]=INF;
        for(int i=1;i<=n;i++) d[i][i]=mp[i][i]=0;
    }

    这里注意,如果给的是边表,必须要这么做,如果给的是矩阵,可以直接忽略这个函数了

    然后是Floyd算法:

    void floyd()
    {
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<k;i++)  
            for(int j=i+1;j<k;j++)   
                mina=min(d[i][j]+mp[j][k]+mp[k][i],mina); 
                 
            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]=min(d[i][j],d[i][k]+d[k][j]),p[i][j]=k;
        }
    }

    如果单纯忽略mina的求解过程,这就是一个裸的,Floyd

    我们再看一下路径是怎么打印的,其实很显然:

    void output(int i,int j)
    {
        if(i==j) return;
        if(p[i][j]==0) printf("%d ",j);
        else{output(i,p[i][j]);output(p[i][j],j);}
    }

    递归的思路还是很明显的

    我们给出完整的实现:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=1005;
     6 const int maxm=2005;
     7 const int INF=0x7fffffff;
     8 int n,m,s,mina=INF;
     9 int d[maxn][maxn],mp[maxn][maxn],p[maxn][maxn];
    10 void init()
    11 {
    12     for(int i=1;i<=n;i++)
    13     for(int j=1;j<=n;j++)
    14         d[i][j]=mp[i][j]=INF;
    15     for(int i=1;i<=n;i++) d[i][i]=mp[i][i]=0;
    16 }
    17 void floyd()
    18 {
    19     for(int k=1;k<=n;k++)
    20     {
    21         for(int i=1;i<k;i++)  
    22         for(int j=i+1;j<k;j++)   
    23             mina=min(d[i][j]+mp[j][k]+mp[k][i],mina); 
    24              
    25         for(int i=1;i<=n;i++)
    26         for(int j=1;j<=n;j++)
    27         if(d[i][k]<INF&&d[k][j]<INF)
    28             d[i][j]=min(d[i][j],d[i][k]+d[k][j]),p[i][j]=k;
    29     }
    30 }
    31 void output(int i,int j)
    32 {
    33     if(i==j) return;
    34     if(p[i][j]==0) printf("%d ",j);
    35     else{output(i,p[i][j]);output(p[i][j],j);}
    36 }
    37 int main()
    38 {
    39     scanf("%d%d%d",&n,&m,&s);
    40     int x,y,z;
    41     init();
    42     for(int i=1;i<=m;i++) {scanf("%d%d%d",&x,&y,&z);mp[x][y]=d[x][y]=min(z,d[x][y]);}
    43     floyd();
    44     for(int i=1;i<=n;i++) printf("%d ",d[s][i]);
    45     return 0;
    46 }

    请注意,请注意,请注意

    在不保证没有重边的情况下,一定要有

    mp[x][y]=d[x][y]=min(z,d[x][y]);

    否则凉凉

  • 相关阅读:
    剩下的树
    守形数
    小白鼠排队(map容器插入数据的四种方法)
    字母统计
    与7无关的数
    ZOJ
    基于js的CURD插件
    API验证插件
    Django之权限管理插件
    Django之信号和序列化
  • 原文地址:https://www.cnblogs.com/aininot260/p/9388103.html
Copyright © 2011-2022 走看看