图论
最短路径
bellman ford算法
题意
N个点的图,2M条正权双向边,W条负权单向边。问图中是否存在负环?
题解
用bellman-ford算法判断。
- bellman-ford算法在挑战程序设计竞赛中的P100
代码
#include <iostream>
using namespace std;
const int MAXN = 10000;
const int INF = (1<<26);
int dis[MAXN];
int F;
int N, M, W;
int m;
struct Edge{ int from, to, cost; } edge[MAXN];
int result;
bool bellman_ford()
{
for(int i = 0; i <= N; i++)
dis[i] = INF;
dis[1] = 0;
bool update;
for(int i = 0; i < N - 1; i++) //之所以是n-1次: 考虑一个最长的最短路径有n-1条边,若边的顺序是逆向的存储的,则一次只用了一条边来更新,一共需要n-1 次
{
update = false;
for(int j = 0; j < m; j++)
{
Edge e = edge[j];
if(dis[e.from] < INF && dis[e.from] + e.cost < dis[e.to])
{
dis[e.to] = dis[e.from] + e.cost;
update = true;
}
}
if(!update)
break;
}
for(int j = 0; j < m; j++) //若第n次还在更新最短路径,则有负权边
{
Edge e = edge[j];
if(dis[e.from] + e.cost < dis[e.to])
return false;
}
return true;
}
bool solve()
{
return !bellman_ford();
}
int main()
{
cin >> F;
while(F--)
{
cin >> N >> M >> W;
int s, e, t;
m = 0;
for(int i = 0; i < M; i++) // bidirectional path
{
cin >> s >> e >> t;
edge[m].from = s , edge[m].to = e , edge[m++].cost = t;
edge[m].from = e , edge[m].to = s , edge[m++].cost = t;
}
for(int i = 0; i < W; i++)
{
cin >> s >> e >> t;
edge[m].from = s , edge[m].to = e , edge[m++].cost = -t;
}
if(!bellman_ford())
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}