题目大意:有n个农场和m条信息每条信息分别表示a农场至少比b农场多c个作物,a农场至多比b农场多c个作物,a农场作物和b农场作物一样多,问有没有符合所有信息的情况
思路:对于差分约束问题,我们如果遇到a-b<=c这样的不等式,就从b到a建一条边,权值为c,如果遇到a-b>=c就从a到b建一条权值为-c的边,如果遇到a=b+c,就从b到a和a到b分别建一条权值为c的边,然后spfa判负环来判断有没有解,接着dis数组的答案就是每个解的可能
#include<bits/stdc++.h>
using namespace std;
const int N = 5e3 + 5, INF = 0x3fffffff;
struct Edge
{
int v, w;
Edge(int a, int b)
{
v = a, w = b;
}
};
vector<Edge>g[N];
int n, m;
int neg[N], dis[N], inq[N];
bool spfa(int s)
{
neg[s] = 1;
for (int i = 1; i <= n; i++)
{
dis[i] = INF;
}
dis[s] = 0;
queue<int>q;
q.push(s);
inq[s]=1;
while (!q.empty())
{
int u = q.front();
q.pop();
inq[u] = 0;
for (int i = 0; i < g[u].size(); i++)
{
int v = g[u][i].v, w = g[u][i].w;
if (dis[u] + w < dis[v])
{
dis[v] = dis[u] + w;
if (!inq[v])
{
inq[v] = 1;
q.push(v);
neg[v]++;
if (neg[v] > n)
{
return 0;
}
}
}
}
}
return 1;
}//spfa模板
int main()
{
cin >> n >> m;
int op;
for (int i = 1; i <= m; i++)
{
scanf("%d", &op);
if (op == 1)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[u].push_back(Edge(v, -w));
}//u-v>=w
else if (op == 2)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[v].push_back(Edge(u, w));
}//u-v<=w
else if (op == 3)
{
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(Edge(v, 0));
g[v].push_back(Edge(u, 0));
}//u=v+0
}
for (int i = 1; i <= n; i++)
{
g[0].push_back(Edge(i, 0));
}//建一个0点通向所有点,确保此图是连通图
if (spfa(0))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
return 0;
}
值