BZOJ 3436: 小K的农场

题意:小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
#include
#include
#include
#include
using namespace std;
const int maxn=10000+10;
int dis[maxn],inq[maxn],n,m,flag=0;
struct node
{
  int to,cost;
};
vector g[maxn];
void spfa(int p)
{
  inq[p]=1;
  for(int i=0;iint 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;
}

你可能感兴趣的:(BZOJ 3436: 小K的农场)