初学最短路算法
2016-01-31 16:44
316 查看
这几天自学了最短路的
Bellman_Ford和Dijkstra算法,通过一道简单题来回顾一下。
题目来源HDU1874.
[align=left]Problem Description[/align]
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
[align=left]Input[/align]
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
[align=left]Output[/align]
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
[align=left]Sample Input[/align]
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
[align=left]Sample Output[/align]
2
-1解一:Dijkstra算法#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mem(a) memset(a, 0, sizeof(a))
#define eps 1e-5
#define M 100005
#define INF 99999
using namespace std;
int vis[10006];
int a,b;
int d[M],w[1005][1005];//d记录从起点到I的最短距离,w[I][j]表示i到j的距离//
int st,en;
void Dij()
{
int v;
for(int i=0;i<a;i++)
{
d[i]=w[st][i];//记录di//
}
d[st]=0;//起点到起点的距离为0//
vis[st]=1;//标记起点//
for(int i=0;i<a;i++)////循环每个点//
{
int tmp=INF;
for(int j=0;j<a;j++)//找到离这个点最近且没被访问的点//
{
if(tmp>d[j]&&!vis[j])
{
tmp=d[j];
v=j;
}
}
vis[v]=1//标记这个点//
for(int k=0;k<a;k++)
{
if(!vis[k])
{
d[k]=min(d[k],d[v]+w[v][k]);//比较从起点直接到k点和起点经过v点到k点的大小//
}
}
}
}
int main()
{
while(cin>>a>>b)
{
mem(vis);
mem(d);
mem(w);
for(int i=0;i<202;i++)
{
for(int j=0;j<202;j++)
{
w[i][j]=INF;//首先不知道I到J的距离,将其视为无穷大,后面,没有i到j的直达路线的话,也是无穷大//
w[i][i]=0;
}
}
for(int i=0;i<b;i++)
{
int aa,bb,cc;
cin>>aa>>bb>>cc;
if(w[aa][bb]>cc)
{
w[aa][bb]=cc;//正确记录i到j的距离//
w[bb][aa]=cc;
}
}
cin>>st>>en;
Dij();
if(d[en]<INF)
{
cout<<d[en]<<endl;
}
else
{
cout<<"-1"<<endl;
}
}
}解二:Bellman_Ford算法#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mem(a) memset(a, 0, sizeof(a))
#define eps 1e-5
#define M 100005
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int a,b,c;
}d[2000];
int aa,bb,st,en;
int dis[M];
void BF(int x,int y)
{
for(int i=0;i<aa;i++)
{
dis[i]=INF;//起点到i点的距离是无穷大//
}
dis[st]=0;
for(int i=0;i<aa-1;i++)//循环aa-1个点//
{
for(int j=0;j<2*bb;j++)
{
if(dis[d[j].b]>dis[d[j].a]+d[j].c)//判断从起点到b和起点经过a点到b点大小//
{
dis[d[j].b]=dis[d[j].a]+d[j].c;
}
}
}
if(dis[en]==INF)
{
cout<<"-1"<<endl;
}
else
{
cout<<dis[en]<<endl;
}
}
int main()
{
while(cin>>aa>>bb)
{
int w,e,r;
for(int i=0;i<bb;i++)
{
cin>>w>>e>>r;
d[i].a=w;
d[i].b=e;
d[i].c=r;
d[i+bb].a=e;
d[i+bb].b=w;
d[i+bb].c=r;
}
cin>>st>>en;
BF(st,en);
}
}
Bellman_Ford和Dijkstra算法,通过一道简单题来回顾一下。
题目来源HDU1874.
[align=left]Problem Description[/align]
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
[align=left]Input[/align]
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
[align=left]Output[/align]
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
[align=left]Sample Input[/align]
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
[align=left]Sample Output[/align]
2
-1解一:Dijkstra算法#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mem(a) memset(a, 0, sizeof(a))
#define eps 1e-5
#define M 100005
#define INF 99999
using namespace std;
int vis[10006];
int a,b;
int d[M],w[1005][1005];//d记录从起点到I的最短距离,w[I][j]表示i到j的距离//
int st,en;
void Dij()
{
int v;
for(int i=0;i<a;i++)
{
d[i]=w[st][i];//记录di//
}
d[st]=0;//起点到起点的距离为0//
vis[st]=1;//标记起点//
for(int i=0;i<a;i++)////循环每个点//
{
int tmp=INF;
for(int j=0;j<a;j++)//找到离这个点最近且没被访问的点//
{
if(tmp>d[j]&&!vis[j])
{
tmp=d[j];
v=j;
}
}
vis[v]=1//标记这个点//
for(int k=0;k<a;k++)
{
if(!vis[k])
{
d[k]=min(d[k],d[v]+w[v][k]);//比较从起点直接到k点和起点经过v点到k点的大小//
}
}
}
}
int main()
{
while(cin>>a>>b)
{
mem(vis);
mem(d);
mem(w);
for(int i=0;i<202;i++)
{
for(int j=0;j<202;j++)
{
w[i][j]=INF;//首先不知道I到J的距离,将其视为无穷大,后面,没有i到j的直达路线的话,也是无穷大//
w[i][i]=0;
}
}
for(int i=0;i<b;i++)
{
int aa,bb,cc;
cin>>aa>>bb>>cc;
if(w[aa][bb]>cc)
{
w[aa][bb]=cc;//正确记录i到j的距离//
w[bb][aa]=cc;
}
}
cin>>st>>en;
Dij();
if(d[en]<INF)
{
cout<<d[en]<<endl;
}
else
{
cout<<"-1"<<endl;
}
}
}解二:Bellman_Ford算法#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mem(a) memset(a, 0, sizeof(a))
#define eps 1e-5
#define M 100005
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int a,b,c;
}d[2000];
int aa,bb,st,en;
int dis[M];
void BF(int x,int y)
{
for(int i=0;i<aa;i++)
{
dis[i]=INF;//起点到i点的距离是无穷大//
}
dis[st]=0;
for(int i=0;i<aa-1;i++)//循环aa-1个点//
{
for(int j=0;j<2*bb;j++)
{
if(dis[d[j].b]>dis[d[j].a]+d[j].c)//判断从起点到b和起点经过a点到b点大小//
{
dis[d[j].b]=dis[d[j].a]+d[j].c;
}
}
}
if(dis[en]==INF)
{
cout<<"-1"<<endl;
}
else
{
cout<<dis[en]<<endl;
}
}
int main()
{
while(cin>>aa>>bb)
{
int w,e,r;
for(int i=0;i<bb;i++)
{
cin>>w>>e>>r;
d[i].a=w;
d[i].b=e;
d[i].c=r;
d[i+bb].a=e;
d[i+bb].b=w;
d[i+bb].c=r;
}
cin>>st>>en;
BF(st,en);
}
}
相关文章推荐
- 信息学奥林匹克竞赛-小玉买文具
- linux下常用的几个时间函数:time,gettimeofday,clock_gettime,_ftime
- 关于字符数组与string类的比较(长度以及)
- UML——类图
- Linux下套接字详解(五)----基于fork多进程的TCP套接字(阻塞/同步/并发)
- JQuery.Ajax()的data参数类型
- 举例讲解C#编程中委托的实例化使用
- Android 实现ListView 内部的点击事件
- 查找 2
- Bug 是改不完的……
- 高精度乘法
- UML——对象图
- 自己动手开发一个 Web 服务器(三)
- linux中的阻塞机制及等待队列
- win10 mac地址修改器
- Linux学习:第九周
- 华为笔试题:奖金提成
- 关于时空穿梭
- clock_gettime(系统调用)
- Spring,hibernate,struts的面试笔试题(含答案)