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\n",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\n");
        else printf("%d\n",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\n",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\n");
        else printf("%d\n",dj[dst]);
    }
    return 0;
}
View Code