zoukankan      html  css  js  c++  java
  • 最短路模板(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!
    ");
                else printf("%.3f
    ",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
    ");
            else printf("%d
    ",dis[t]);
        }
        return 0;
    }

  • 相关阅读:
    忘记密码破解
    关于本地变量的理解
    MVC的请求过程(或者MVC三者的关系)
    static 静态 关键字
    博客搬家通知
    C#一个可以马上跑起来的反射例子Assembly的使用
    C#之DateTime日期格式解析
    AddressParsing在C#中好用的地址拆分地址结构化库Net5
    C#中获取本地IP地址方法
    ComdeDom生成对象Emit之引用其他成员类库
  • 原文地址:https://www.cnblogs.com/waryan/p/12559184.html
Copyright © 2011-2022 走看看