zoukankan      html  css  js  c++  java
  • Dijkstra模板

     Dijkstra是求最短路径,从未选过点中找最短的一条路,然后更新其他点到起点的距离。例如选择的最短点为k,则dj[k]表示起点到k之间的距离,此时更新其他点到起点的距离,dj[j] = min(dj[j],dj[k]+dj[k][j]);dj[j]比较原来的长度与经过k掉再到j点的长度,取最小。

    模板如下:

    void Dijkstra()
    {
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=n;++i)
            dj[i] = Map[0][i];
        vis[0] = 1;
        for(int i=1;i<=n;++i)
        {
            int mindj = INF;
            int pos;
            for(int j=1;j<=n;++j)
            {
                if(dj[j]<mindj&&!vis[j])
                {
                    mindj = dj[j];
                    pos = j;
                }
            }
            vis[pos] = 1;
            for(int j=1;j<=n;++j)
            {
                if(!vis[j] && dj[j] > dj[pos] + Map[pos][j])
                    dj[j] = dj[pos] + Map[pos][j];
            }
        }
    }
    View Code

    hdu2066

    由于多个起点,只要设置多个起点到0起点的距离为0即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define INF (1<<30)
    #define N   (1000+100)
    
    int Map[N][N];
    int n;
    int dj[N],vis[N];
    
    
    void Dijkstra()
    {
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=n;++i)
            dj[i] = Map[0][i];
        vis[0] = 1;
        for(int i=1;i<=n;++i)
        {
            int mindj = INF;
            int pos;
            for(int j=1;j<=n;++j)
            {
                if(dj[j]<mindj&&!vis[j])
                {
                    mindj = dj[j];
                    pos = j;
                }
            }
            vis[pos] = 1;
            for(int j=1;j<=n;++j)
            {
                if(!vis[j] && dj[j] > dj[pos] + Map[pos][j])
                    dj[j] = dj[pos] + Map[pos][j];
            }
        }
    }
    
    int main()
    {
        int t,s,d;
        while(~scanf("%d%d%d",&t,&s,&d))
        {
            n = 0;
            for(int i=0;i<N;++i)
                for(int j=0;j<N;++j)
                {
                    if(i != j)  Map[i][j] = INF;
                    else Map[i][j] = 0;
                }
            for(int i=0;i<t;++i)
            {
                int a,b,time;
                scanf("%d%d%d",&a,&b,&time);
                Map[a][b] = Map[b][a] = min(Map[a][b],time);
                n = max(max(a,b),n);
            }
            int src[N],dst[N];
            for(int i=0;i<s;++i)
            {
                scanf("%d",&src[i]);
                Map[0][src[i]] = 0;
            }
            for(int i=0;i<d;++i)
                scanf("%d",&dst[i]);
            Dijkstra();
            int res = INF;
            for(int i=0;i<d;++i)
                res = min(res,dj[dst[i]]);
            printf("%d
    ",res);
        }
        return 0;
    }
    View Code

    hdu1874

    跟2066一样,每次两点之间会有多条路,需要取最小的那条算,无语。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define INF (1<<30)
    #define N (200+10)
    
    int Map[N][N];
    int n;
    int dj[N],vis[N];
    
    void Dijkstra()
    {
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=n;++i)
            dj[i] = Map[0][i];
        vis[0] = 1;
        for(int i=1;i<=n;++i)
        {
            int pos,mindj = INF;
            for(int j=1;j<=n;++j)
                if(!vis[j]&&dj[j]<mindj)
                {
                    mindj = dj[j];
                    pos = j;
                }
            vis[pos] = 1;
            for(int j=1;j<=n;++j)
                if(!vis[j])
                    dj[j] = min(dj[j],dj[pos]+Map[pos][j]);
        }
    }
    
    int main()
    {
        int m;
        while(~scanf("%d%d",&n,&m))
        {
            for(int i=0;i<=n;++i)
                for(int j=0;j<=n;++j)
                {
                    if(i != j) Map[i][j] = INF;
                    else Map[i][j] = 0;
                }
            for(int i=0;i<m;++i)
            {
                int a,b,x;
                scanf("%d%d%d",&a,&b,&x);
                Map[a+1][b+1] = Map[b+1][a+1] = min(Map[a+1][b+1],x);
            }
            int s,t;
            scanf("%d%d",&s,&t);
            ++s,++t;
            Map[0][s] = 0;
            Dijkstra();
            if(dj[t] >= INF) printf("-1
    ");
            else printf("%d
    ",dj[t]);
        }
        return 0;
    }
    View Code

    hdu3790

    二维最短路径,求最短路径,如果最短路径有多条,求费用最少。原理一样,不难

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define INF (1<<30)
    #define  N (1000+10)
    
    int n,m;
    int Map[N][N],Price[N][N];
    int dj[N],cost[N],vis[N];
    
    void Dijkstra()
    {
        memset(vis,0,sizeof(vis));
        vis[0] = 1;
        for(int i=0;i<=n;++i)
        {
            dj[i] = Map[0][i];
            cost[i] = Price[0][i];
        }
        for(int i=1;i<=n;++i)
        {
            int mindj=INF,pos;
            for(int j=1;j<=n;++j)
                if(!vis[j]&&dj[j]<mindj)
                {
                    mindj = dj[j];
                    pos = j;
                }
            vis[pos] = 1;
            for(int j=1;j<=n;++j)
                if(!vis[j]&&(dj[j] > dj[pos] + Map[pos][j]||
                             (dj[j]==dj[pos] + Map[pos][j] &&
                              cost[j] > cost[pos] + Price[pos][j])))
                {
                    dj[j] = dj[pos] + Map[pos][j];
                    cost[j] = cost[pos] + Price[pos][j];
                }
        }
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m),n&&m)
        {
            for(int i=0;i<=n;++i)
                for(int j=0;j<=n;++j)
                {
                    if(i != j) Map[i][j] = INF;
                    else Map[i][j] = 0;
                }
            memset(Price,0,sizeof(Price));
            for(int i=0;i<m;++i)
            {
                int a,b,d,p;
                scanf("%d%d%d%d",&a,&b,&d,&p);
                if(d < Map[a][b] || (d==Map[a][b]&&p < Price[a][b]))
                {
                    Map[a][b] = Map[b][a] = d;
                    Price[a][b] = Price[b][a] = p;
                }
            }
            int s,t;
            scanf("%d%d",&s,&t);
            Map[0][s] = 0;
            Dijkstra();
            printf("%d %d
    ",dj[t],cost[t]);
        }
        return 0;
    }
    View Code

    hdu2112

    用map把地名换成数字。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define INF (1<<30)
    #define N    (160)
    
    map<string,int> msi;
    int Map[N][N];
    int cnt;
    int vis[N],dj[N];
    void Dijkstra()
    {
        memset(vis,0,sizeof(vis));
        vis[0] = 1;
        for(int i=0;i<=cnt;++i)
            dj[i] = Map[0][i];
        for(int i=1;i<=cnt;++i)
        {
            int pos,mindj = INF;
            for(int j=1;j<=cnt;++j)
                if(!vis[j] && dj[j] < mindj)
                {
                    pos = j;
                    mindj = dj[j];
                }
            vis[pos] = 1;
            for(int j=1;j<=cnt;++j)
                if(!vis[j]) dj[j] = min(dj[j],dj[pos]+Map[pos][j]);
        }
    
    }
    int main()
    {
        int n;
        while(~scanf("%d",&n),n!=-1)
        {
            for(int i=0;i<N;++i)
                for(int j=0;j<N;++j)
                {
                    if(i!=j) Map[i][j] = INF;
                    else Map[i][j] = 0;
                }
            msi.clear();
            char a[40],b[40];
            int ia,ib,t,dst;
            scanf("%s%s",a,b);
            cnt = 0;
            msi[a] = ++cnt;
            dst = (strcmp(a,b)==0?cnt:++cnt);
            msi[b] = dst;
            Map[0][1] = 0;
            for(int i=0;i<n;++i)
            {
                scanf("%s%s%d",a,b,&t);
                pair<map<string,int>::iterator,bool>pmb = msi.insert(pair<string,int>(a,0));
                if(pmb.second) msi[a] = ++cnt;
                pmb = msi.insert(pair<string,int>(b,0));
                if(pmb.second) msi[b] = ++cnt;
                //换成下面部分也可以
                /*(if(!msi[a])
                    msi[a] = ++cnt;
                if(!msi[b])
                    msi[b] = ++cnt;
                */
                ia = msi[a];
                ib = msi[b];
                if(t < Map[ia][ib])
                    Map[ia][ib] = Map[ib][ia] = t;
            }
            Dijkstra();
            if(dj[dst] >= INF) printf("-1
    ");
            else printf("%d
    ",dj[dst]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    使用MySQL存储过程连续插入多条记录
    为什么编程语言以及数据库要从1970年1月1日开始计算时
    关于shtml页面include问题解决方案
    简单实用的FTP操作类
    js实现完美身份证号有效性验证
    .htaccess文件的建立和rewrite_module的启用
    php冒泡排序
    php实现汉诺塔问题(递归)
    简单的mysql数据库备份程序
    选择排序的php实现
  • 原文地址:https://www.cnblogs.com/jlyg/p/7404082.html
Copyright © 2011-2022 走看看