HDU 2544-最短路(Dijkstra算法 Floyd算法 SPFA算法,3种实现代码,包含路径)

来源:互联网 发布:淘宝商城摩托车 编辑:程序博客网 时间:2024/05/20 07:35


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544

最短路

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 67093    Accepted Submission(s): 29309


Problem Description
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

 

Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
 

Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间

Sample Input
2 11 2 33 31 2 52 3 53 1 20 0
 

Sample Output
32
//3种最短路算法, 直接套模板//由于数据比较水,所以Floyd算法也能过#include <stdio.h>#include <queue>#include <stack>#include <string.h>#include <algorithm>#define maxn 1005#define inf 0x3f3f3f3fusing namespace std;int dist[maxn];       //记录源点到各个点的最短路径长度int edge[maxn][maxn];//邻接矩阵存边int pre[maxn];      //记录一个路径中,到达某个点的前一个点bool vis[maxn];     //记录某个元素是否在队列内int cnt[maxn];    //记录一个元素入队的次数,如果大于nodenum-1,那么就存在负权回路int Fdist[maxn][maxn]; //记录Floyd算法的任意两点的最短距离int Fpre[maxn][maxn]; //记录一个路径中两点之间的中间点queue<int>q;          //SPFA算法中用到的队列void Floyd(int orig, int nodenum){    for(int i=1; i<=nodenum; i++)        for(int j=1; j<=nodenum; j++)            {                Fdist[i][j] = edge[i][j];                Fpre[i][j] = -1;            }    for(int k=1; k<=nodenum; k++)        for(int i=1; i<=nodenum; i++)        {            if(Fdist[i][k]!=inf)            {                for(int j=1; j<=nodenum; j++)                {                    if(Fdist[i][j] > Fdist[i][k]+Fdist[k][j])                    {                        Fdist[i][j] = Fdist[i][k]+Fdist[k][j];                        Fpre[i][j] = k;                    }                }            }        }}void Dijkstra(int orig, int nodenum){memset(vis, 0, sizeof(vis));memset(pre, -1, sizeof(pre));for(int i=1; i<=nodenum; i++){dist[i] = edge[orig][i];if(dist[i]!=inf)pre[i] = orig;}vis[orig] = 1;for(int i=1; i<nodenum; i++){int u = orig, cntmin = inf;for(int j=1; j<=nodenum; j++){if(!vis[j]&&dist[j]<cntmin){u = j;cntmin = dist[j];}}vis[u] = 1;for(int j=1; j<=nodenum; j++){if(!vis[j] && dist[j] > dist[u]+edge[u][j]){dist[j] = dist[u]+edge[u][j];pre[j] = u;}}}}bool SPFA(int orig, int nodenum){while(!q.empty())q.pop();memset(vis, false, sizeof(vis));memset(pre, -1, sizeof(pre));memset(cnt, 0, sizeof(cnt));for(int i=1; i<=nodenum; i++)dist[i] = inf;vis[orig] = true;pre[orig] = orig;cnt[orig]++;    dist[orig] = 0;q.push(orig);while(!q.empty()){int u = q.front();q.pop();vis[u] = false;for(int v=1; v<=nodenum; v++){if(dist[v] > dist[u]+edge[u][v]){dist[v] = dist[u]+edge[u][v];pre[v] = u;if(!vis[v]){vis[v] = true;cnt[v]++;q.push(v);if(cnt[v]>nodenum-1)return false;}}}}return true;}//Floyd算法,点s到t的路径void Floyd_path(int s, int t){    if(Fdist[s][t]==inf)        {            printf("%d---%d--no load\n", s, t);            return;        }    if(Fpre[s][t]==-1)        return;    int k = Fpre[s][t];    Floyd_path(s, k);    printf("%d->", k);    Floyd_path(k, t);}//Dijkstra和SPFA算法,最短路的路径void p_path(int orig, int node){stack<int>path;while(node!=pre[node]){path.push(node);node = pre[node];}printf("%d->", node);while(!path.empty()){printf("%d->", path.top());path.pop();}printf("\n\n");}void DisPath(int orig, int nodenum){for(int i=1; i<=nodenum; i++){if(dist[i]!=inf){printf("%d到%d的最短路径长度是:%d\n", orig, i, dist[i]);printf("路径是:");p_path(orig, i);}else{printf("%d到%d没有路径\n\n", orig, i);}}}int main(){int nodenum, edgenum, orig;  //结点数,边数,源点while(scanf("%d%d", &nodenum, &edgenum), nodenum+edgenum){orig = 1;for(int i=0; i<=nodenum; i++)for(int j=1; j<=nodenum; j++)edge[i][j] = i==j?0:inf;for(int i=1; i<=edgenum; i++){int u, v, cost;scanf("%d%d%d", &u, &v, &cost);edge[v][u] = edge[u][v] = min(edge[u][v], cost);}        //SPFA(orig, nodenum);        Dijkstra(orig, nodenum);        //Floyd(orig, nodenum);        //printf("%d\n", Fdist[1][nodenum]);        printf("%d\n", dist[nodenum]);}return 0;}



还有Bellman算法,但是提交后,一直runtime error,下面是代码(该代码未ac)
//Bellman算法#include <stdio.h>#include <string.h>#include <algorithm>#include <stack>#include <map>#define maxn 1005#define inf 0x3f3f3f3fusing namespace std;map<int, int>mp;struct Edge{int u, v;}edge[maxn<<1];int dist[maxn];int pre[maxn];void p_path(int orig, int node){stack<int>path;while(node!=pre[node]){path.push(node);node = pre[node];}printf("%d->", node);while(!path.empty()){printf("%d->", path.top());path.pop();}printf("\n\n");}void DisPath(int orig, int nodenum){for(int i=1; i<=nodenum; i++){if(dist[i]!=inf){printf("%d到%d的最短路径长度是:%d\n", orig, i, dist[i]);printf("路径是:");p_path(orig, i);}else{printf("%d到%d没有路径\n\n", orig, i);}}}bool Bellman(int orig,int nodenum, int edgenum){for(int i=1; i<=nodenum; i++){dist[i] = inf;pre[i] = -1;}dist[orig] = 0;pre[orig] = orig;for(int i=1; i<nodenum; i++){for(int j=0; j<edgenum; j++){if(dist[edge[j].v] > dist[edge[j].u] + mp[edge[j].u*maxn + edge[j].v]){pre[edge[j].v] = edge[j].u;dist[edge[j].v] = dist[edge[j].u] + mp[edge[j].u*maxn + edge[j].v];}}}bool res = true;for(int j=0; j<edgenum; j++){if(dist[edge[j].v] > dist[edge[j].u] + mp[edge[j].u*maxn + edge[j].v]){res = false;break;}}return res;}int main(){    int u[maxn], v[maxn], cost[maxn];int nodenum, edgenum, orig;while(scanf("%d%d", &nodenum, &edgenum), nodenum+edgenum){orig = 1;int e = 0;mp.clear();for(int i=1; i<=edgenum; i++){scanf("%d%d%d", &u[i], &v[i], &cost[i]);}//因为图是无向图,且可重边,所以用map[u*maxn + v]表示点u与点v的边的权值for(int i=1; i<=edgenum; i++){if(mp[u[i]*maxn+v[i]]>0){mp[v[i]*maxn+u[i]] = mp[u[i]*maxn+v[i]] = min(mp[u[i]*maxn+v[i]], cost[i]);}else{edge[e++].u = u[i];edge[e-1].v = v[i];edge[e++].u = v[i];edge[e-1].v = u[i];mp[v[i]*maxn+u[i]] = mp[u[i]*maxn+v[i]] = cost[i];}}if(Bellman(orig, nodenum, e)){    printf("%d\n", dist[nodenum]);   // DisPath(orig, nodenum);}elseprintf("存在负权回路\n");}return 0;}



阅读全文
0 0
原创粉丝点击