sicily 1031. Campus

本文详细介绍并实现了Dijkstra算法,这是一种用于解决图中单源最短路径问题的经典算法。文章通过具体的代码示例展示了如何使用优先队列来优化算法性能,并介绍了相关数据结构如边的结构体和邻接表的应用。
#include<iostream>  
#include<vector>
#include<map>
#include<queue>
#include<string>
#include<cstring>
using namespace std;
const int MAXN = 205;
const int INF = 1000000;
int dis[MAXN];
int n;//结点数量
typedef pair<int,int> pii;
struct edge//建立边的结构体
{
int v; //v表示一条边的终点,w表示边的权重
int w;
edge(int vv,int ww)
{
v = vv;
w = ww;
}
};
int dijkstra(int st,int ed,vector<edge> G[])
{
priority_queue<pii,vector<pii >,greater<pii > > q; //优先队列是默认大元素先出队,所以要改成小元素先出队
for(int i = 0;i < n;++i)
dis[i] = (i == st ? 0 : INF);//初始化dis
q.push(make_pair(dis[st],st));//将起点插入队列,pair默认是优先处理first元素,故插入优先队列先弹出队列的优先级是依据dis[]大小
while(!q.empty())
{
pii u = q.top(); //每次都弹出最小值,再在这最小值基础上修改其它结点的最短距离,就是Dijkstra算法
q.pop();
int x = u.second;
if(u.first != dis[x]) continue;//可避免结点的重复拓展,提高优先队列处理速度。去掉这一句也不影响程序的正确性,只是更费时,也能通过sicily
//相当于Dijkstra算法对每个结点都会进行一次标号。 这里每一个元素出队都相当于处理一次已标号结点,如果出队的这个元素,他带的dis,和当前的dis不相同,证明这个结点是被处理过的
for(int i = 0;i < G[x].size();++i) //在邻接表中长度各不同,所以用size(),即vector做邻接表更方便
{
int y = G[x][i].v;
int w = G[x][i].w;
if(dis[y] > dis[x] + w)
{
dis[y] = dis[x] + w;
q.push(make_pair(dis[y],y));
}
}
}
if(dis[ed] == INF)
return -1;
else return dis[ed];
}

int main()
{
int t,w;
string u,v;
cin >> t;
while(t--)
{
n = 0;//初始化结点数目
int e;
cin >> e;
map<string,int> M; //把每个地址转化成相对应的唯一的数字
vector<edge> G[MAXN];//邻接表
for(int i = 0;i < e;++i)
{
cin >> u >> v >> w;//输入点1,点2, 权值
if(!M.count(u))
M.insert(make_pair(u,n++));
if(!M.count(v))
M.insert(make_pair(v,n++));//利用map关联容器为字符串型的边进行标号
edge E1(M[v],w);//初始化边,必须调换结点才能插入vector邻接表
edge E2(M[u],w);
G[M[u]].push_back(E1);//建立邻接表
G[M[v]].push_back(E2);
}
string st,ed;
cin >> st >> ed;
if(st == ed)
cout << 0 << endl;
else if(!M.count(st) || !M.count(ed))
cout << -1 << endl;
else
cout << dijkstra(M[st],M[ed],G) << endl;
}
return 0;
}

 


转载于:https://www.cnblogs.com/mjc467621163/archive/2011/07/04/2097672.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值