原题链接:
http://soj.sysu.edu.cn/1321
思路:这是一道求单源最短路的题,笔者分别用Dijkstra和Bellman-Ford两种算法求解。我们知道,Dijkstra算法对只含有正权边的图管用,一般情况下(不用二分堆)复杂度是O(V^2)。而BellmanFord算法对含有负权边的图一样管用,其复杂度为O(V*E),但如果图是稀疏图,此算法的效率更好!以下代码,Bellman-Ford算法的ac时间为0.03s,Dijkstra的ac时间为0.37s,这应该也是因为图比较稀疏的原因。
代码一(Dijkstra算法):
#include <iostream>
using namespace std;
#define INF 999999999
int Matrix[105][105],DisMatrix[105][105];
bool Visited[105][105];
int Dijkstra(pair<int,int> start,pair<int,int> end, int m, int n){
pair<int,int> MinDistancePoint;
int nPoint=m*n;
//初始化
Visited[start.first][start.second]=true;
DisMatrix[start.first][start.second]=Matrix[start.first][start.second];
MinDistancePoint=start;
for(int i=1;i<nPoint;i++){
int x=MinDistancePoint.first,y=MinDistancePoint.second;
//更新到start点的值
if((x-1>=1)&&(!Visited[x-1][y])&&((DisMatrix[x][y]+Matrix[x-1][y])<DisMatrix[x-1][y]))
DisMatrix[x-1][y]=DisMatrix[x][y]+Matrix[x-1][y];
if((y-1>=1)&&(!Visited[x][y-1])&&((DisMatrix[x][y]+Matrix[x][y-1])<DisMatrix[x][y-1]))
DisMatrix[x][y-1]=DisMatrix[x][y]+Matrix[x][y-1];
if((x+1<=m)&&(!Visited[x+1][y])&&((DisMatrix[x][y]+Matrix[x+1][y])<DisMatrix[x+1][y]))
DisMatrix[x+1][y]=DisMatrix[x][y]+Matrix[x+1][y];
if((y+1<=n)&&(!Visited[x][y+1])&&((DisMatrix[x][y]+Matrix[x][y+1])<DisMatrix[x][y+1]))
DisMatrix[x][y+1]=DisMatrix[x][y]+Matrix[x][y+1];
int MinDistance=INF;
//查找下一个visited的点(即未visited中最近的点)
for(int a=1;a<=m;a++)
for(int b=1;b<=n;b++){
if((!Visited[a][b])&&(DisMatrix[a][b]<MinDistance)){
MinDistance=DisMatrix[a][b];
MinDistancePoint.first=a;
MinDistancePoint.second=b;
}
}
//访问最小的点
Visited[MinDistancePoint.first][MinDistancePoint.second]=true;
}
return DisMatrix[end.first][end.second];
}
int main(){
int T;
cin>>T;
while(T--){
int m,n;
cin>>m>>n;
if((m==0)||(n==0))
cout<<0<<endl;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
cin>>Matrix[i][j];
DisMatrix[i][j]=INF;
Visited[i][j]=false;
}
pair<int,int> start,end;
cin>>start.first>>start.second>>end.first>>end.second;
cout<<Dijkstra(start,end,m,n)<<endl;
}
return 0;
}
代码二(Bellman-Ford算法):
#include <iostream>
#include <queue>
using namespace std;
#define INF 999999999
int Matrix[105][105],DisMatrix[105][105];
int BellmanFord(pair<int,int> start,pair<int,int> end, int m, int n){
queue <pair<int,int>> UpdatePoint;
int nPoint=m*n;
//初始化
DisMatrix[start.first][start.second]=Matrix[start.first][start.second];
UpdatePoint.push(start);
for(int i=1;i<nPoint;i++){
queue <pair<int,int>> NextUpdatePoint;
//更新
while(!UpdatePoint.empty()){
pair<int,int> point;
point=UpdatePoint.front();
int x=point.first;
int y=point.second;
if((x-1>=1)&&((DisMatrix[x][y]+Matrix[x-1][y])<DisMatrix[x-1][y])){
DisMatrix[x-1][y]=DisMatrix[x][y]+Matrix[x-1][y];
NextUpdatePoint.push(make_pair(x-1,y));
}
if((y-1>=1)&&((DisMatrix[x][y]+Matrix[x][y-1])<DisMatrix[x][y-1])){
DisMatrix[x][y-1]=DisMatrix[x][y]+Matrix[x][y-1];
NextUpdatePoint.push(make_pair(x,y-1));
}
if((x+1<=m)&&((DisMatrix[x][y]+Matrix[x+1][y])<DisMatrix[x+1][y])){
DisMatrix[x+1][y]=DisMatrix[x][y]+Matrix[x+1][y];
NextUpdatePoint.push(make_pair(x+1,y));
}
if((y+1<=n)&&((DisMatrix[x][y]+Matrix[x][y+1])<DisMatrix[x][y+1])){
DisMatrix[x][y+1]=DisMatrix[x][y]+Matrix[x][y+1];
NextUpdatePoint.push(make_pair(x,y+1));
}
UpdatePoint.pop();
}
//更新下轮需要更新的点
while(!NextUpdatePoint.empty()){
UpdatePoint.push(NextUpdatePoint.front());
NextUpdatePoint.pop();
}
}
return DisMatrix[end.first][end.second];
}
int main(){
int T;
cin>>T;
while(T--){
int m,n;
cin>>m>>n;
if((m==0)||(n==0))
cout<<0<<endl;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
cin>>Matrix[i][j];
DisMatrix[i][j]=INF;
}
pair<int,int> start,end;
cin>>start.first>>start.second>>end.first>>end.second;
cout<<BellmanFord(start,end,m,n)<<endl;
}
return 0;
}