题目链接:http://soj.me/1031
题目大意:
给出四个校区的一些地点之间的距离,地点名用字符串来表示,问某两个地点之间的最短路径长度,典型的单源最短路径题目
思路:
单源最短路径问题可以用dijkstra算法实现,这道题比较麻烦的是用字符串来表示地点,我用的处理方法是建立map得到地点名字到序号的映射,对于每个新输入的地点名字,先在map里面查找是否存在,如果不存在就绑定一个新的序号.地点之间的距离用邻接矩阵来存放 题目:sicily1031(单源最短路径),注意一共最多可能有100个节点,最大路径,最大可以去到100*100=10000
#include<iostream>
#include<string>
#include<map>
#include<memory.h>
using namespace std;
#define MAX 250
int djstra(int a[][MAX],int snode,int tnode,int nodelen){
bool visit[MAX];
int dist[MAX];
memset(visit, false, sizeof(visit));
for(int i = 0;i<250;i++)
dist[i] = 100000;
dist[snode] = 0;
visit[snode]=true;
for (int i = 0; i < nodelen; i++){
// 寻找最短路径(s,t),同时把t加入S集合
int min =100000;
int min_j =snode;
for(int j = 0; j < nodelen; j++){
if (!visit[j] && dist[j] < min) {
min = dist[j];//记录最小值和最小值的下标
min_j = j ;
}
}
visit[min_j] = true;
// 松弛边(t,v),其中v为顶点
for(int k = 0; k < nodelen; k++){
if (!visit[k] && dist[k]>dist[min_j]+a[min_j][k] )
dist[k] = dist[min_j]+a[min_j][k];
}
}
// 非连通图
if(!visit[tnode])
return -1;
// 连通图
else{
return dist[tnode];
}
};
int main() {
int c;
//测试用例数目
cin>>c;
while(c--){
int a[MAX][MAX];
for(int i = 0;i<250;i++)
for(int j = 0;j<250;j++){
a[i][j] = 100000;
if(i==j)
a[i][j]=0;
}
map<string,int> mymap;
int n;
string snode,tnode;
cin>>n;
//总的node数目
int i = 0;
while(n--){
string s,t;
int d,si,ti;
cin>>s>>t>>d;
// 字符串到整数数组的映射
if(mymap.find(s)==mymap.end()){
mymap[s] = i;
si = i;
i++;
}
else{
si = mymap[s];
}
if(mymap.find(t)==mymap.end()){
mymap[t] = i;
ti = i;
i++;
}
else{
ti = mymap[t];
}
a[si][ti] = d;
a[ti][si] = d;
}
cin>>snode>>tnode;
// 起点等于终点
if(tnode==snode)
cout<<"0"<<endl;
else
// 起点或者终点不存在
if(!mymap.count(snode)||!mymap.count(tnode))
cout<<"-1"<<endl;
else
cout<<djstra(a, mymap[snode], mymap[tnode],i)<<endl;
}
}
总结
dijstra算法模板:
dijkstra的过程
初始将顶点s加入到S中,并更新s到其他顶点的路径权值。
选择最短路径dist(s,t),并将t加入到S中。
在第一步中得到t,对于u∈V-S,松弛边(t,v)。
重复上述过程,直到所有的顶点都被加入到集合S中为止。
可以给出伪代码:
// 初始化
for i=[0,n)
dist[i] = tab[0][i]
visit[0] = true;
for i=[1,n)
// 寻找最短路径(s,t),同时把t加入S集合
min = MAX_VALUE
for j=[0,n)
if !visit[j] && dist[j]<min
min = dist[j]
visit[j] = true
// 松弛边(t,v),其中v为顶点
for k=[0,n)
if !visit[k] && dist[k]>dist[j]+tab[j][k]
dist[k] = dist[j]+tab[j][k]