正常spfa中加入time数组,循环判断一个点是否入队并更新了n次以上注意是 > n!!其余的没有什么问题
扩展的还有,寻找所有负环上的点,这个可以在spfa中time 发现负环的时候,对那个点进行dfs操作,找到所有的负环上的点即可
void dfs(int u) { cir[u] = 1; for(int i = id[u];~i;i = edge[i].pre) { if(!cir[edge[i].to]) dfs(edge[i].to); } }
一下负权回路代码以poj3259为例(poj又挂了,暂时还没发交题测试,欢迎大家来找bug)
/* spfa负环的判断 */ #include <iostream> #include <cstdio> #include <string.h> #include <queue> #include <algorithm> #define inf (1 << 29) using namespace std; typedef long long ll; const int maxn = 600; const int maxm = 3e3; int id[maxn],cnt; struct node{ int to,cost,pre; }e[maxm * 2]; int dis[maxn]; int vis[maxn]; int time[maxn]; queue<int> q; void init() { while(q.size())q.pop(); memset(time,0,sizeof(time)); memset(vis,0,sizeof(vis)); memset(id,-1,sizeof(id)); cnt = 0; } void add(int from,int to,int cost) { e[cnt].to = to; e[cnt].cost = cost; e[cnt].pre = id[from]; id[from] = cnt++; } int spfa(int s,int n) { for(int i= 0;i <= n;i++) dis[i] = inf; q.push(s); vis[s] = 1; time[s] = 1; dis[s] = 0; while(q.size()) { int now = q.front(); q.pop(); vis[now] = 0; for(int i = id[now];~i;i = e[i].pre) { int to = e[i].to; int cost = e[i].cost; if(dis[to] > dis[now] + cost) { dis[to] = dis[now] + cost; if(!vis[to]) { vis[to] = 1; q.push(to); if(++time[to] > n) return 0; } } } } return 1; } int main() { int t; scanf("%d",&t); while(t--) { int n,m,k; scanf("%d%d%d",&n,&m,&k); init(); int a,b,x; for(int i = 1;i <= m;i++) { scanf("%d%d%d",&a,&b,&x); add(a,b,x); add(b,a,x); } for(int i = 1;i <= k;i++) { scanf("%d%d%d",&a,&b,&x); add(a,b,-x); } int op = spfa(1,n); if(op) printf("NO "); else printf("YES "); } return 0; }