讲解:https://www.cnblogs.com/murmured/p/5004082.html
https://www.cnblogs.com/void/archive/2011/08/26/2153928.html
https://blog.csdn.net/qq_29538137/article/details/78569815
两种不等式
第一种: A-B<=val,建一条从B出发到A边权为val的边并跑最短路,求解满足所有条件的最大值。
第二种:A-B>=val,建一条从B出发到A边权为val的边并跑最长路,求解满足所有条件的最小值。
添加一个源点与其他点连接,以防出现不连通有些负环判断不到的情况。
题目链接:https://vjudge.net/problem/HYSBZ-3436
判断是否有解,最长路最短路都可以,需要注意spfa的bfs版本判断负环慢,在此题中超时,dfs版本可以过。
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int maxn=10050;
const int inf=0x3f3f3f3f;
int flag;
struct Edge
{
int from,to,dist;
Edge() {}
Edge(int u,int v,int d):from(u),to(v),dist(d)
{
}
};
struct SPFA
{
int n,m;
vector <Edge> edges;//保存所有边
vector <int> G[maxn];//只保存边的编号
bool done[maxn];//访问标记
int d[maxn];//到每个点的距离
bool inq[maxn];
int cnt[maxn];
void init(int n)//传参为顶点数
{
this->n=n;
for(int i=0; i<=n; i++)
{
G[i].clear();
}
edges.clear();
}
void addedge(int from,int to,int dist)
{
edges.push_back(Edge(from,to,dist));
m=edges.size();
G[from].push_back(m-1);
}
void Spfa (int s)
{
done[s]=true;
int len=G[s].size();
Edge e;
for(int i=0; i<len; i++)
{
e=edges[G[s][i]];
if(d[e.to]>e.dist+d[s])
{
if(done[e.to])
{
flag=0;
return ;
}
d[e.to]=e.dist+d[s];
Spfa(e.to);
}
}
done[s]=false;
}
} spfa;
int main()
{
flag=1;
int n,m;
scanf("%d%d",&n,&m);
int a,b,c,id;
for(int i=0; i<m; i++)
{
scanf("%d",&id);
if(id==1)
{
scanf("%d%d%d",&a,&b,&c);
spfa.addedge(a,b,-c);
}
else if(id==2)
{
scanf("%d%d%d",&a,&b,&c);
spfa.addedge(b,a,c);
}
else
{
scanf("%d%d",&a,&b);
spfa.addedge(a,b,0);
spfa.addedge(b,a,0);
}
}
spfa.n=n;
for(int i=1; i<=n; i++)
{
spfa.addedge(0,i,0);
spfa.d[i]=inf;
spfa.done[i]=false;
}
spfa.d[0]=0;
spfa.Spfa(0);
if(flag==1)
{
printf("Yes\n");
}
else
printf("No\n");
return 0;
}