点击:理解请参考
例题:https://www.luogu.com.cn/problem/P1807
如果求最短路径 :vis[nex] = min(vis[nex], vis[now]+B[now][k]);
f [ ]数组你要先初始化 无穷大
即:for(int i=1; i<=n; i++) vis[i] = 999999;
如果求最长路径: vis[nex]=max(vis[nex], vis[now]+B[now][k]);
f [ ]数组你要先初始化 无穷小
即 :for(int i=1; i<=n; i++) vis[i] = 0;
还有
就是这个spfa算法跟 关键路径(拓扑) 挺像的 就稍微改改
例题正确代码:
//思路 建立两个表 位置相同 存边的长度
#include<bits/stdc++.h>
using namespace std;
vector <int> G[1515]; //存点
vector <int> B[1515]; //存边
int vis[50010]; //最大长度
int main()
{
int n, m; //点数 n 边数 m
cin >> n >> m;
for(int i=1; i<=m; i++)
{
int a, b, w; // a -> b 边的值为 w
cin >> a >> b >> w;
G[a].push_back(b);
B[a].push_back(w);
}
queue <int>q;
q.push(1);
while(!q.empty())
{
//这里每次弹出来的数都是以 1号结点发散的 不在乎是否 rudp[i]== 0
int now = q.front();
q.pop();
for(int k=0; k<G[now].size(); k++)
{
int nex = G[now][k];
if(vis[nex]<vis[now]+B[now][k])
{
vis[nex] = max(vis[nex], vis[now]+B[now][k]);
q.push(nex);
}
/-----------------------------------------------------|
|/*如果求最短路径就是这个
| 但是记得把 for(i<=N) vis[i] = 99999;
| vis[1] = 0;
| int nex = G[now][k];
| if(vis[nex]>vis[now]+B[now][k])
| {
| vis[nex] = min(vis[nex], vis[now]+B[now][k]);
| q.push(nex);
| }
|*/
/-----------------------------------------------------|
}
}
if(vis[n]>0) //如果 1 能走到 n
cout << vis[n];
else
printf("-1");
return 0;
}
错误代码:
错误原因:https://www.luogu.com.cn/discuss/show/300476
//思路 建立两个表 位置相同 存边的长度
#include<bits/stdc++.h>
using namespace std;
vector <int> G[1515]; //存点
vector <int> B[1515]; //存边
int rud[50010]; //存入度的数量
int vis[50010]; //最大长度
int ndm[5000]; //标记 1 到 n 的路径 判断走不走得到
int main()
{
int n, m; //点数 n 边数 m
cin >> n >> m;
for(int i=1; i<=m; i++)
{
int a, b, w; // a -> b 边的值为 w
cin >> a >> b >> w;
G[a].push_back(b);
B[a].push_back(w);
rud[b]++;
}
ndm[1] = 1;
queue <int>q;
q.qush(1);
while(!q.empty())
{ //这里每次弹出来的都是按拓扑序列的
int now = q.front();
q.pop();
for(int k=0; k<G[now].size(); k++)
{
int nex = G[now][k];
if(ndm[now] == 1) ndm[nex] = 1;
rud[nex]--;
if(rud[nex] == 0)
{
q.push(nex);
rud[nex]--;
}
vis[nex] = max(vis[nex], vis[now]+B[now][k]);
}
}
if(ndm[n] == 1 && m!=0) //如果 1 能走到 n
cout << vis[n];
else
printf("-1");
return 0;
}
//发现问题了 按拓扑序列做题不太好 应该按 bfs来广搜
//因为 它这有影响的 拓扑序列