题意:小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述:农场a比农场b至少多种植了c个单位的作物,农场a比农场b至多多种植了c个单位的作物,农场a与农场b种植的作物数一样多。但是,由于小K的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。
差分约束系统= =,我对每个节点的设定是至多为多少,相当于一开始是INF,然后我们加边将它的范围逐渐减小,不存在解的情况就是里面存在负环,对于a比b至少多种c,可以转化为b比a至多多种c,而a和b一样,就是a比b至多多种b,之后连边就好了。
Tips:对于一样的边,千万不要加两次,否则就是人为构造一个环..
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
const int maxn=10000+10;
int dis[maxn],inq[maxn],n,m,flag=0;
struct node
{
int to,cost;
};
vector<node> g[maxn];
void spfa(int p)
{
inq[p]=1;
for(int i=0;i<g[p].size();i++)
{
node e=g[p][i];int v=e.to;
if(dis[v]>dis[p]+e.cost)
{
if(inq[v])
{
flag=1;
break;
}
dis[v]=dis[p]+e.cost;
spfa(v);
}
}
inq[p]=0;
}
int main()
{
//freopen("3436.in","r",stdin);
//freopen("3436.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int op,a,b,c;
scanf("%d%d%d",&op,&a,&b);
if(op==1)
{
scanf("%d",&c);
g[a].push_back((node){b,-c});
}
if(op==2)
{
scanf("%d",&c);
g[b].push_back((node){a,c});
}
else
{
g[a].push_back((node){b,0});
//g[b].push_back((node){a,0});
}
}
memset(dis,127/2,sizeof(dis));
for(int i=1;i<=n;i++)
dis[i]=0,spfa(i);
if(flag) puts("No");
else puts("Yes");
return 0;
}