题目链接 点击打开链接
判断是否有负权回路,bf模板,对所有点进行n-1次松弛操作,如果不存在负权回路,就找找出了所有点到起点的最短路,否则还能继续松弛。
松弛操作:如果一个点p到起点start的距离大于从起点到另一个点other,再到p的距离,就把start->p的距离修改为start->other->p的距离,这个叫松弛。
#include <cstdio> #include <iostream> #include <cstring> #define INF 0xfffffff using namespace std; int n,m,w; int G[505][505]; //图 struct Edge{ //边起点终点和权重 int start,end; int weight; }edge[3000]; int dis[505]; //起点1到i的距离 int num = 0; void BellmanFord(){ for(int i = 2;i <= n;i++) dis[i] = G[1][i]; //初始化 dis[1] = 0; //到自身距离为0 //n-1次松弛操作 for(int i = 1;i < n;i++) for(int j = 0;j < num;j++){ if(dis[edge[j].end] > dis[edge[j].start] + edge[j].weight) dis[edge[j].end] = dis[edge[j].start] + edge[j].weight; //松弛 } bool flag = false; //判断是否还能继续松弛 for(int j = 0;j < num;j++){ if(dis[edge[j].end] > dis[edge[j].start] + edge[j].weight){ flag = true; break; } } if(flag){ //还能松弛说明有负权回路 printf("YES\n"); }else{ printf("NO\n"); } } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&w); int a,b,c; for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) G[i][j] = INF; for(int i = 1;i <= n;i++) G[i][i] = 0; for(int i = 0;i < m;i++){ scanf("%d%d%d",&a,&b,&c); G[a][b] = G[b][a] = min(G[a][b],c); } for(int i = 0;i < w;i++){ scanf("%d%d%d",&a,&b,&c); G[a][b] = -c; } num = 0; for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++){ if(i == j || G[i][j] == INF) continue; edge[num].start = i; edge[num].end = j; edge[num].weight = G[i][j]; num++; } BellmanFord(); } return 0; }