对于
n
n
n个物品,给出
m
m
m个限制关系,分别是:
1.
a
a
a比
b
b
b至少多种
c
c
c单位的作物。
2.
a
a
a比
b
b
b至多多种
c
c
c单位的作物。
3.
a
a
a和
b
b
b的作物数相等。
求问是否满足这样的一种情形,符合所有的限制关系。
不妨记
f
(
∗
)
f(*)
f(∗)表示
∗
*
∗的作物数,显然各条件等价于:
1.
f
(
a
)
−
f
(
b
)
≥
c
f(a)-f(b)\geq c
f(a)−f(b)≥c
2.
f
(
b
)
−
f
(
a
)
≥
−
c
f(b)-f(a)\geq-c
f(b)−f(a)≥−c
3.
f
(
a
)
−
f
(
b
)
≥
0
,
f
(
b
)
−
f
(
a
)
≥
0
f(a)-f(b)\geq0,f(b)-f(a)\geq0
f(a)−f(b)≥0,f(b)−f(a)≥0
对于每个不等式,后者向前者连边,然后求最长路。出现正环对应无解。
注意:求最长路的时候,各个点应该设置为负无穷,而不是0。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e4+7;
struct edge { int v,w; };
vector<edge> go[N];
int dis[N],cnt[N];
bool inq[N];
int n,m;
bool spfa() {
queue<int> q;
q.push(0);
for(int i=1;i<=n;i++)
dis[i]=-1e9;
while(!q.empty()) {
int u=q.front();
q.pop();
inq[u]=0;
for(auto &e:go[u]) {
int v=e.v,w=e.w;
if(dis[v]<dis[u]+w) {
dis[v]=dis[u]+w;
if(!inq[v]) {
inq[v]=1;
q.push(v);
if(++cnt[v]>=n) {
return 0;
}
}
}
}
}
return 1;
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
int opt,a,b,c;
scanf("%d",&opt);
if(opt==1) {
scanf("%d%d%d",&a,&b,&c);
go[b].push_back({a,c});
}
else if(opt==2) {
scanf("%d%d%d",&a,&b,&c);
go[a].push_back({b,-c});
}
else {
scanf("%d%d",&a,&b);
go[a].push_back({b,0});
go[b].push_back({a,0});
}
}
for(int i=1;i<=n;i++)
go[0].push_back({i,0});
bool ans=spfa();
if(ans) puts("Yes");
else puts("No");
return 0;
}