最短路专题

来源:互联网 发布:上海茜昶网络培训的 编辑:程序博客网 时间:2024/05/16 01:48

 

HDU 2544 最短路 http://acm.hdu.edu.cn/showproblem.php?pid=2544

题意:计算从1到n的最短时间。

最短路模板题。。。

 

Source Code:

(Dijkstra):

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int inf=0x3f3f3f3f;const int nv=102;int map[nv][nv];int dis[nv];bool s[nv];int n,m;int dijkstra(int src,int n){    int i,j,u,tmp;    for(int i=1;i<=n;i++){        dis[i]=map[src][i];        s[i]=false;    }    s[src]=true;    dis[src]=0;    for(i=1;i<n;i++){        tmp=inf;        for(j=1;j<=n;j++){            if(!s[j]&&dis[j]<tmp){                tmp=dis[j];                u=j;            }        }        s[u]=true;        for(j=1;j<=n;j++){            if(!s[j]&&map[u][j]+dis[u]<dis[j])                dis[j]=map[u][j]+dis[u];        }    }    return dis[n];}int main(){    while(~scanf("%d %d",&n,&m),n||m){       memset(map,inf,sizeof(map));       while(m--){            int u,v,w;            scanf("%d %d %d",&u,&v,&w);            if(map[u][v]>w) map[u][v]=map[v][u]=w;       }       printf("%d\n",dijkstra(1,n));    }    return 0;}


 

(Bellman Ford):

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int inf=0x3f3f3f3f;const int nv=105;struct Edge{    int u,v,w;}gra[nv*nv];int dis[nv];void BellmanFord(int n,int m){    memset(dis,inf,sizeof(dis));    dis[1]=0;    for(int i=1;i<n;i++){        for(int j=1;j<=m;j++){            if(dis[gra[j].u]+gra[j].w<dis[gra[j].v]) dis[gra[j].v]=dis[gra[j].u]+gra[j].w;            if(dis[gra[j].v]+gra[j].w<dis[gra[j].u]) dis[gra[j].u]=dis[gra[j].v]+gra[j].w;        }    }}int main(){    int n,m;    while(scanf("%d %d",&n,&m),n+m){        for(int i=1;i<=m;i++){            int u,v,w;            scanf("%d %d %d",&u,&v,&w);            gra[i].u=u,gra[i].v=v,gra[i].w=w;        }        BellmanFord(n,m);        printf("%d\n",dis[n]);    }    return 0;}


(spfa):

#include<iostream>#include<cstdio>#include<queue>#include<algorithm>using namespace std;const int maxn=105;const int INF=0x3f3f3f3f;int n,m;int map[maxn][maxn],dis[maxn];bool mark[maxn];int Spfa(int src,int des){    for(int i=0;i<=n;i++){        mark[i]=false;        dis[i]=INF;    }    queue<int>Q;    mark[src]=true;    dis[src]=0;    Q.push(src);    while(!Q.empty()){        int first=Q.front();        Q.pop();        mark[first]=false;        for(int i=1;i<=n;i++){            if(dis[first]+map[first][i]<dis[i]){                if(!mark[i]){                    Q.push(i);                    mark[i]=true;                }                dis[i]=dis[first]+map[first][i];            }        }    }    return dis[des];}int main(){    while(scanf("%d %d",&n,&m),n+m){        int a,b,c;        for(int i=1;i<=n;i++){            for(int j=1;j<=n;j++)                map[i][j]=INF;        }        while(m--){            scanf("%d %d %d",&a,&b,&c);            if(map[a][b]>c) map[a][b]=map[b][a]=c;        }        printf("%d\n",Spfa(1,n));    }    return 0;}


 

 

 

 

HDU 1548 A strange lift  http://acm.hdu.edu.cn/showproblem.php?pid=1548

题意:一幢N层的楼,每层有一个按钮,可以上或者下X层(当然不能跑到地下或超过楼的层数),问从A层到B层最少按几次按钮。

题解:在纸上画一下很容易想到是单源最短路。由于数据规模很小用BFS亦可。

 

Source Code:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int inf=0x3f3f3f3f;const int maxn=205;int Map[maxn][maxn],dis[maxn];bool s[maxn];int n,a,b;bool OK(int x){    if(x>0&&x<=n) return true;    return false;}int dijkstra(int Src,int End){    int i,j,u,tmp;    for(i=1;i<=n;i++){        dis[i]=Map[Src][i];        s[i]=false;    }    s[Src]=true;    dis[Src]=0;    for(i=1;i<n;i++){        tmp=inf;        for(j=1;j<=n;j++){            if(!s[j]&&dis[j]<tmp){                tmp=dis[j];                u=j;            }        }        s[u]=true;        for(j=1;j<=n;j++){            if(dis[j]>dis[u]+Map[u][j])                dis[j]=dis[u]+Map[u][j];        }    }    return dis[End]>=inf?-1:dis[End];}int main(){    while(scanf("%d",&n),n){        scanf("%d %d",&a,&b);        memset(Map,inf,sizeof(Map));        int x;        for(int i=1;i<=n;i++){            scanf("%d",&x);            if(OK(i+x)) Map[i][i+x]=1;            if(OK(i-x)) Map[i][i-x]=1;        }        if(a==b){            printf("0\n");            continue;        }        if(!OK(a)||!OK(b)){            printf("-1\n");            continue;        }        printf("%d\n",dijkstra(a,b));    }    return 0;}


 HDU 2066  一个人的旅行 http://acm.hdu.edu.cn/showproblem.php?pid=2066

题意:一个人想去D个地方,可以从T个地方出发,问到达某个想去的地方的最短时间。

题解:多源最短路,但用Folyd会超时,可以对每个出发点进行单源最短路求法(Dijkstra)。

 

Source Code:

 

#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int inf=0x3f3f3f3f;const int maxn=1005;int Map[maxn][maxn],dis[maxn];int T,S,D,maxC;bool mark[maxn];int start[maxn],want[maxn];void dijkstra(int src){    int i,j,u,tmp;    for(i=1;i<=maxC;i++){        dis[i]=Map[src][i];        mark[i]=false;    }    dis[src]=0;    mark[src]=true;    for(i=1;i<maxC;i++){        tmp=inf;        for(j=1;j<=maxC;j++){            if(!mark[j]&&dis[j]<tmp){                u=j;                tmp=dis[j];            }        }        mark[u]=true;        for(j=1;j<=maxC;j++){            if(!mark[j]&&dis[j]>dis[u]+Map[u][j])                dis[j]=dis[u]+Map[u][j];        }    }}int main(){    //freopen("D:\in.txt","r",stdin);    while(scanf("%d %d %d",&T,&S,&D)==3){        memset(Map,inf,sizeof(Map));        maxC=0;        int a,b,t,ans=inf;        for(int i=1;i<=T;i++){            scanf("%d %d %d",&a,&b,&t);            if(Map[a][b]>t) Map[a][b]=Map[b][a]=t;            if(a>maxC) maxC=a;            if(b>maxC) maxC=b;        }        for(int i=1;i<=S;i++)            scanf("%d",&start[i]);        for(int i=1;i<=D;i++)            scanf("%d",&want[i]);        for(int i=1;i<=S;i++){            dijkstra(start[i]);            for(int j=1;j<=D;j++)                if(dis[want[j]]<ans) ans=dis[want[j]];        }        printf("%d\n",ans);    }    return 0;}


HDU 2112 HDU Today http://acm.hdu.edu.cn/showproblem.php?pid=2112

题意:求从出发地start到目的地end的最短距离。

分析:用C++ STL中的map将字符串转换成整数,就是典型的最短路了。

 

Source Code:

#include <iostream>#include <stdio.h>#include <memory.h>#include <string>#include <algorithm>#include <queue>#include <map>using namespace std;const int N = 155;const int INF = 99999999;map<string, int> mp;map<string, bool> bp;int way[N][N], dist[N];bool visit[N];string begin, end;int n, ans;void init()     //初始化函数{    int i, j;    mp.clear(); //清空映射mp    bp.clear(); //清空映射bp    for(i = 0; i < N; i++)        for(j = 0; j < N; j++)            if(i == j) way[i][j] = 0;            else way[i][j] = INF;}void input()    //输入函数{    int i, cost;    ans = 1;    string str1, str2;    cin >> begin >> end;    mp[begin] = 1;      //mp映射该string为1    bp[begin] = true;   //bp映射该string为true    if(!bp[end])    {        mp[end] = ++ans;        bp[end] = true;    }    for(i = 1; i <= n; i++)    {        cin >> str1 >> str2 >> cost;        if(!bp[str1])        {            mp[str1] = ++ans;            bp[str1] = true;        }        if(!bp[str2])        {            mp[str2] = ++ans;            bp[str2] = true;        }        way[mp[str1]][mp[str2]] = way[mp[str2]][mp[str1]] = cost;    }}void spfa(){    int i, now;    memset(visit, false, sizeof(visit));    for(i = 0; i <= ans; i++) dist[i] = INF;    dist[1] = 0;    queue<int> Q;    Q.push(1);    visit[1] = true;    while(!Q.empty())    {        now = Q.front();        Q.pop();        visit[now] = false;        for(i = 1; i <= ans; i++)        {            if(dist[i] > dist[now] + way[now][i])            {                dist[i] = dist[now] + way[now][i];                if(visit[i] == false)                {                    Q.push(i);                    visit[i] = true;                }            }        }    }}int main(){    while(scanf("%d", &n))    {        if(n == -1) break;        init();        input();        spfa();        if(dist[mp[end]] != INF) printf("%d\n", dist[mp[end]]);        else printf("-1\n");    }    return 0;}


 

HDU 1217 Arbitrage http://acm.hdu.edu.cn/showproblem.php?pid=1217

题意:给出几种货币及货币间的汇率,问某种货币是否可以经过兑换其他的货币实现套利(就是兑换了一圈比原来的多)。

分析:多源最短路,结合C++ STL map和Folyd稍作变化即可。

 

Source Code:

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <queue>#include <map>using namespace std;const double inf=0x3f3f3f3f;const int maxn=50;map<string,int>mp;map<string,bool>bp;bool visit[maxn];double way[maxn][maxn],dis[maxn];int n,m,cas=0;double len;bool Floyd(){    for(int k=1;k<=n;k++){        for(int i=1;i<=n;i++){            for(int j=1;j<=n;j++){                if(way[i][j]<way[i][k]*way[k][j])                    way[i][j]=way[i][k]*way[k][j];            }        }    }    for(int i=1;i<=n;i++){        for(int j=1;j<=n;j++){            if(way[i][i]>1)                return true;        }    }    return false;}int main(){    //freopen("D:\in.txt","r",stdin);    while(scanf("%d",&n),n){        string str,str1,str2;        for(int i=1;i<=n;i++){            cin>>str;            mp[str]=i;        }        scanf("%d",&m);        memset(way,0,sizeof(way));        for(int i=1;i<=m;i++){            cin>>str1>>len>>str2;            way[mp[str1]][mp[str2]]=len;        }        if(Floyd()) printf("Case %d: Yes\n",++cas);        else        printf("Case %d: No\n",++cas);    }    return 0;}


 

 HDU 1535 Invitation Cards http://acm.hdu.edu.cn/showproblem.php?pid=1535

题意:有P个站点q条路线,且两个站点之间是单向的。求从1号站点到其他站点的最短路只和+从其他站点回到1号站点的最短路之和。

分析:去的时候求1到其他站点的单源最短路之和即可。对于回来的,是求其他所有站点到1号站点的最短路之和,很自然可以想到将图反向重建,再求1号站点到其他站点的单源最短路即可。

 

Source Code:

#include<iostream>#include<cstdio>#include<queue>using namespace std;const int N=1000001;const int INF=0x3f3f3f3f;struct node{    int v,w,next;}edgego[N],edgeback[N];int headgo[N],headback[N],dist[N];bool mark[N];int p,q;void spfa(node edge[],int head[]){    memset(mark,false,sizeof(mark));    for(int i=2;i<=p;i++)        dist[i]=INF;    dist[1]=0;    queue<int>Q;    Q.push(1);    while(!Q.empty()){        int x=Q.front();        Q.pop();        mark[x]=false;        for(int e=head[x];e!=-1;e=edge[e].next){            if(dist[edge[e].v]>dist[x]+edge[e].w){                dist[edge[e].v]=dist[x]+edge[e].w;                if(!mark[edge[e].v]){                    mark[edge[e].v]=true;                    Q.push(edge[e].v);                }            }        }    }}int main(){    int t,ans,u,v,w;scanf("%d",&t);    while(t--){        ans=0;        scanf("%d %d",&p,&q);        memset(headgo,-1,sizeof(int)*(p+1));        memset(headback,-1,sizeof(int)*(p+1));        for(int i=1;i<=q;i++){            scanf("%d %d %d",&u,&v,&w);            edgego[i].v=v;            edgego[i].w=w;            edgego[i].next=headgo[u];            headgo[u]=i;            edgeback[i].v=u;            edgeback[i].w=w;            edgeback[i].next=headback[v];            headback[v]=i;        }        spfa(edgego,headgo);        for(int j=2;j<=p;j++)            ans+=dist[j];        spfa(edgeback,headback);        for(int l=2;l<=p;l++)            ans+=dist[l];        printf("%d\n",ans);    }    return 0;}


 

 

 

原创粉丝点击