spfa 怎么解决 最长路的问题 (为无向图且保证出现正环)

SPFA可以处理负环,记录一个点出现的次数,只要这个点出现次数超过n次(n为总点数),就证明有负环

事实上,把正边权改为负边权是可以的,也很方便;但是有时SPFA可以直接修改算法中的大于号或小于号,这不适用于Dijkstra

边权取负是最常用的,题目一般会保证没有负环,如果有的话一般会让输出impossible这样的字串

下面是我SPFA的一个板子

#include<bits/stdc++.h>

#define INF 0x3f3f3f3f

using namespace std;

struct Edge

{

int to,next,len;

}edge[(int)1e5+5];

struct Node

{

int head,dis;

bool vis;

}node[(int)1e5+5];

int cnt;

int addEdge(int u,int v,int w)

{

edge[++cnt].len=w;

edge[cnt].to=v;

edge[cnt].next=node[u].head;

node[u].head=cnt;

}

int u,v,w;

int n,m;

int SPFA()

{

queue<int>q;

for(int i=1;i<=n;i++)

{

node[i].dis=INF;

node[i].vis=false;

}

node[1].dis=0;

node[1].vis=true;

q.push(1);

while(not q.empty())

{

int u=q.front();

q.pop();

node[u].vis=false;

for(int e=node[u].head;e;e=edge[e].next)

{

int v;

if(node[v=edge[e].to].dis<=node[u].dis+edge[e].len)continue;

node[v].dis=node[u].dis+edge[e].len;

/*只要在这里加一个判断,

c[v]++;//更新出现次数

if(c[v]>n) return 0;*/

if(!node[v].vis)

{

q.push(v);

node[v].vis=true;

}

}

}

if(node[n].dis==INF)

{

puts("impossible");

exit(0);

}

return node[n].dis;

}

int main()

{

cin>>n>>m;

for(int i=1;i<=m;i++)

{

cin>>u>>v>>w;

addEdge(u,v,w);//根据题目要求是否取相反数

}

cout<<SPFA()<<endl;

return 0;

}

纯手打,很累,不理解继续问,求采纳