【第二十二课】最短路:多源最短路floyd算法(acwing-852 spfa判断是否存在负环 / acwing-854 / c++代码)

目录

acwing-852 

代码如下 

一些解释 

acwing-854

foyld算法思想

代码如下

一些解释


acwing-852 

【第二十二课】最短路:多源最短路floyd算法(acwing-852 spfa判断是否存在负环 / acwing-854 / c++代码)_第1张图片

在spfa求最短路的算法基础上进行修改。

代码如下 

#include
#include
#include
#include
using namespace std;
const int N=2010,M=10010;

int n,m;
int h[N],e[M],ne[M],w[M],idx;
int dist[N],cnt[N];
bool st[N];
void add(int a,int b,int c)
{
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}
bool spfa()
{
    queue q;
    for(int i=1;i<=n;i++)
    {
        st[i]=1;
        q.push(i);
    }
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        st[t]=0;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>dist[t]+w[i])
            {
                dist[j]=dist[t]+w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n)return 1;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=1;
                }
            }
        }
    }
    return 0;
}
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof h);
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    if(spfa())puts("Yes");
    else puts("No");
    return 0;
}

一些解释 

图中左边表示求最短路的函数 右边是判断是否存在负环的代码。对修改的地方都做了解释,相信应该很清楚啦 

【第二十二课】最短路:多源最短路floyd算法(acwing-852 spfa判断是否存在负环 / acwing-854 / c++代码)_第2张图片

1.dist数组:

在这段代码中,dist数组是用来存储每个节点的最短距离的。但是由于所有节点在开始时都被加入到了队列中,所以在算法的执行过程中,dist数组会被逐步更新。也就是说,即使我们没有显式地初始化dist数组,它的值也会在算法的执行过程中被正确地计算出来。

我们可以理解为dist数组存的是图中其他顶点到该点的距离中,最短的那个距离。也算是过程中顺便求了一遍多源最短路问题。

2. if(cnt[j]>=n)return 1;

抽屉原理是一个基本的组合数学原理,简单来说就是:如果有n个抽屉和n+1个物品,那么至少有一个抽屉里会有两个或更多的物品。

在这段代码中,cnt[j]表示从任意节点到节点j的最短路径中 边的数量。如果cnt[j]大于等于节点的总数n,那么说明至少有一个节点被访问了两次,这意味着存在一个环。

acwing-854

【第二十二课】最短路:多源最短路floyd算法(acwing-852 spfa判断是否存在负环 / acwing-854 / c++代码)_第3张图片

foyld算法思想

通过遍历所有可能的中间节点,检查是否存在一条路径通过这个中间节点可以使得某对节点之间的距离更短。

由于所有顶点都有可能是其他路径上的中间节点,因此我们对于每个节点对的遍历要经过n次。(外层循环)

内层的两个循环的作用就是遍历所有顶点对。 

代码如下

思想明白之后,代码应该不难理解。 

#include
#include
#include
using namespace std;
const int N=210,INF=1e9;
int d[N][N];//二维矩阵存储稠密图 
int n,m,q;
void floyd()
{
    for(int k=1;k<=n;k++)//k作为中间节点
    {
        for(int i=1;i<=n;i++)//遍历所有的节点对(i, j)
        {
            for(int j=1;j<=n;j++)
            {
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
}
int main()
{
    cin>>n>>m>>q;
    //d[i][j]表示i j两点之间的最短距离
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j)d[i][j]=0;//自环记为没有边
            else d[i][j]=INF;            
        }
    }
    while(m--)
    {
        int a,b,w;
        cin>>a>>b>>w;
        d[a][b]=min(d[a][b],w);//处理重边
    }
    floyd();
    while(q--)//处理询问
    {
        int a,b;
        cin>>a>>b;

        if(d[a][b]>INF/2)puts("impossible");
        else cout<

一些解释

if(d[a][b]>INF/2)puts("impossible");
    else cout<

用d[a][b]>INF/2来作为是否存在最短距离的条件:

//存在负权边,所以距离为inf也会被更新.

这句解释我更能理解一点hh.

下面是bing的解释 

【第二十二课】最短路:多源最短路floyd算法(acwing-852 spfa判断是否存在负环 / acwing-854 / c++代码)_第4张图片

关于这个问题我不太确定qwq欢迎交流指点


好啦,最短路问题也算是写完了。

有问题欢迎指出,一起加油!!! 

你可能感兴趣的:(算法--学习笔记,算法,c++,最短路)