最短路模板(dij+floyd)

时间:2020-03-24
本文章向大家介绍最短路模板(dij+floyd),主要包括最短路模板(dij+floyd)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一:dijkstra模板(n2

int dis[maxn],vis[maxn];
void dijkstra(int src)
{
    int i,k,j,tmp;
    for(i=1;i<=n;++i)
        dis[i]=mt[src][i],vis[i]=0;
    dis[src]=0;
    vis[src]=1;
    for(i=0;i<n-1;++i){//n个点选n-1条边
        tmp=INF;
        for(j=1;j<=n;++j){//取出此时最短距离
            if(!vis[j]&&tmp>=dis[j]){
                k=j;tmp=dis[j];
            }
        }
        if(tmp==INF) break;//无最短距离-无解
        vis[k]=1;
        for(j=1;j<=n;++j){
            if(!vis[j]&&dis[j]>dis[k]+mt[k][j])
                dis[j]=dis[k]+mt[k][j];//更新src到j的距离
        }

    }
}

二:floyd弗洛伊德(n3)

for(int k=1; k<=n; ++k)
{
    for(int i=1; i<=n; ++i)
    {
        for(int j=1; j<=n; ++j)
        {
            if(arr[i][k]+arr[k][j]<arr[i][j])//判断是否更新距离
                arr[i][j]=arr[i][k]+arr[k][j];
        }
    }
}

1.使用floyd时记得初始化距离

for(int i=1; i<=n; ++i)
    for(int j=1; j<=n; ++j)
        arr[i][j]= {i==j?0:INF};

2.floyd的单点修改后更新最短距离:Roads in Berland

  题目大意:给出个点距离矩阵后,如若要修改某个距离,每次修改后回答每对点之间最短距离和

ll dis[maxn][maxn];
int n,m;
int main()
{
    cin>>n;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j)
            cin>>dis[i][j];
    }
    int k;cin>>k;
    while(k--){
        int x,y,val;cin>>x>>y>>val;
        if(dis[x][y]>val)
            dis[x][y]=dis[y][x]=val;//修改两点距离
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                dis[i][j]=min(dis[i][j],min(dis[i][x]+dis[x][j],dis[i][y]+dis[y][j])),dis[j][i]=dis[i][j];//更新每个经过这条边的最短距离
        ll ans=0;
        for(int i=1;i<=n;++i)
            for(int j=1;j<i;++j)
            ans+=dis[i][j];//求每对点之间的最短距离和
        cout<<ans<<endl;

    }
}

  dijkstra经典例题:find the safest road-求最安全的路-'最短路'变形,此题变为乘法计算

const int maxn=1010;
int n;int s,e;
double m[maxn][maxn],dis[maxn];
int vis[maxn];
void dij()
{
    int i,j,k;
    double tmp;
    for(i=1;i<=n;++i)
        dis[i]=m[s][i],vis[i]=0;
    dis[s]=1;vis[s]=1;
    for(i=0;i<n-1;++i){
        tmp=0;k=-1;
        for(j=1;j<=n;++j)
            if(!vis[j]&&dis[j]>tmp)
            tmp=dis[j],k=j;
        if(tmp==0) break;
        vis[k]=1;
        for(j=1;j<=n;++j)
            if(!vis[j]&&dis[k]*m[k][j]>dis[j])//此处略有修改算的是乘法求最安全的路
            dis[j]=dis[k]*m[k][j];
    }
}
int main()
{IO;
    while(~scanf("%d",&n)){

        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
            scanf("%lf",&m[i][j]);
        int q;scanf("%d",&q);
        for(int p=0;p<q;++p){
            scanf("%d%d",&s,&e);
            dij();
            if(dis[e]==0) printf("What a pity!\n");
            else printf("%.3f\n",dis[e]);
        }
    }
}

一般dij例题:畅通工程续

const int maxn=210;
int mt[maxn][maxn];
int n,m;
int dis[maxn],vis[maxn];
void dijkstra(int src)
{
    for(int i=0;i<n;++i)
        dis[i]=mt[src][i],vis[i]=0;
    dis[src]=0;
    vis[src]=1;
    int i,k,j;
    for(i=0;i<n;++i){
        int tmp=INF;
        for(j=0;j<n;++j){
            if(!vis[j]&&tmp>=dis[j]){
                k=j;tmp=dis[j];
            }
        }
        if(tmp==INF) break;
        vis[k]=1;
        for(j=0;j<n;++j){
            if(!vis[j]&&dis[j]>dis[k]+mt[k][j])
                dis[j]=dis[k]+mt[k][j];
        }

    }
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        int x,y,val;
        for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
                mt[i][j]=INF;
        for(int i=0;i<m;++i){
            scanf("%d%d%d",&x,&y,&val);
            if(mt[x][y]>val) mt[x][y]=mt[y][x]=val;//重边
        }
        int s,t;scanf("%d%d",&s,&t);
        dijkstra(s);
        if(dis[t]==INF) printf("-1\n");
        else printf("%d\n",dis[t]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/waryan/p/12559184.html