单元最短路算法 但是有可能被卡(什么菊花图啥的)
一般在没有明确负坏的条件下 都是用 效率更高一点的dijkstra算法
链式前向星 是一种以边为存储核心的 存边方法
主要是有以下几个关键的部分
用结构体来存边
至于这个next 因为遍历方法实际上是一个倒序遍历 但是这里却是next我觉得怎么应该用pre呢
next 实际上就是 上一个点的信息
//MAXN 点的数量 MAXM边的数量
struct node
{
int to,w,next;// to代表去向,w代表边的权值,next记录当前这个点上一个的边出现的位置
}edge[MAXM];// 边的数量
int cnt;// 用来记录边的数量
int head[MAXN];// 记录 以某一点为起点的边出现的位置
//这个head数组的初始化为0还是-1都是开始的 相应的要把第一条变得编号变成1或0就可以了
int vis[MAXN];
int dis[MAXN];
int usetime[MAXN];//使用次数
void add(int u,int v,int w)//加边函数
{
edge[++cnt].to=u;
edge[cnt].w = w;
edge[cnt].next = head[u];//上一次还没更新前的位置
head[u] = cnt;
}
int spfa(int s)// 队列实现 链式前向星存边 spfa 通过遍历顶点来完成
{
queue<int>q;
q.push(s);
dis[s] = 0;
//usetime[s] = 1;
vis[s] = 1;
while(!q.empty())
{
int top = q.front();
q.pop();
vis[top] = 0;
usetime[top]++;
if(ustime[top] > n)
return 0;// 某一个点的入队次数大于点的个数 存在负坏
for(int i = head[top];i != 0;i = e[i].next)// 有负环他就可以无线松弛 然后 入队 次数一定会大于n的
{
if(dis[e[i].to] > dis[top] + e[i].w)
{
dis[e[i].to] = dis[top] + e[i].w;// 松弛操作
if(!vis[e[i].to)
{
vis[e[i].to] = 1;
q.push(e[i].to)
}
}
}
}
return 1;
}
这样就可以通过spfa来求出最短路 以及 是否存在负环了
int main()
{
int u,v,w,s; //u--->v的权值为w,s为起始点
cin >> n >> m >> s;
memset(dis,inf,sizeof(dis));
for(int i = 0;i < m;i++){
cin >> u >> v >> w;
add(u,v,w);
//add(v,u,w);加不加双向边看题意
}
spfa(s);
for(int i = 1;i <= n;i++){
if(dis[i] != inf)
cout << dis[i] << " ";
else
cout << "inf" << " ";
}
return 0;
}
spfa 加 链式前向星存图和遍历
最新推荐文章于 2021-03-14 10:09:49 发布