【BZOJ3436】小K的农场

题目:BZOJ3436

解析:

  差分约束系统。
  分析一下三种情况:
  1.农场 a a a比农场 b b b至少多种植了 c c c个单位的作物
  即 a ≥ b + c − > b ≤ a − c a\geq b+c->b\leq a-c ab+c>bac a a a b b b连一条长度为 − c -c c的单向边。
  2.农场 a a a比农场 b b b至多多种植了 c c c个单位的作物。
  即 a ≤ b + c a\leq b+c ab+c b b b a a a连一条长度为 c c c的单向边。
  3.农场 a a a与农场 b b b种植的作物数一样多。
  即 a = b − > a ≤ b a=b->a\leq b a=b>ab b ≥ a b\geq a ba a , b a,b a,b之间连一条长度为 0 0 0的双向边。
  然后跑SPFA最短路判负环就行了,注意这道题 B F S BFS BFS T T T D F S DFS DFS才能过。

代码(BFS):

#include <bits/stdc++.h>
using namespace std;

const int Max=10005;
int n,m,size;
int first[Max],sum[Max],v[Max],dis[Max];
struct shu{int to,next,len;}e[Max<<2];

inline int get_int()
{
    int x=0,f=1;char c;
    for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
    if(c=='-') f=-1,c=getchar();
    for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    return x*f;
}

inline void build(int x,int y,int z)
{
    e[++size].next=first[x],first[x]=size,e[size].to=y,e[size].len=z;
}
inline bool SPFA()
{
    queue<int>q;
    memset(dis,0x3f,sizeof(dis));
    q.push(0),sum[0]++,dis[0]=0;
    while(q.size())
    {
      int p=q.front();q.pop();v[p]=0;
      for(int u=first[p];u;u=e[u].next)
      {
      	int to=e[u].to;
      	if(dis[to]>dis[p]+e[u].len)
      	{
      	  dis[to]=dis[p]+e[u].len;
      	  if(!v[to])
      	  {
          	sum[to]++;
            if(sum[to] >= n) return 0; 
            v[to] = 1,q.push(to);
      	  }
      	}
      }
    }
    return 1;
}

int main()
{
    n=get_int(),m=get_int();
    while(m--)
    {
      int tag=get_int(),x=get_int(),y=get_int(),z;
      if(tag==1) z=get_int(),build(x,y,-z);
      if(tag==2) z=get_int(),build(y,x,z);
      if(tag==3) build(x,y,0),build(y,x,0);
    }
    for(int i=1;i<=n;i++) build(0,i,0);
    if(SPFA()) puts("Yes");
    else puts("No");
    return 0;
}

代码(DFS):

#include <bits/stdc++.h>
using namespace std;

const int Max=10005;
int n,m,size,flag;
int first[Max],sum[Max],v[Max],dis[Max];
struct shu{int to,next,len;}e[Max<<2];

inline int get_int()
{
    int x=0,f=1;char c;
    for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
    if(c=='-') f=-1,c=getchar();
    for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    return x*f;
}

inline void build(int x,int y,int z)
{
    e[++size].next=first[x],first[x]=size,e[size].to=y,e[size].len=z;
}
inline void SPFA(int p)
{
    v[p]=1;
    for(int u=first[p];u;u=e[u].next)
    {
      int to=e[u].to;
      if(dis[to]>dis[p]+e[u].len)
      {
      	if(v[to]) {flag=1;return;}
      	dis[to]=dis[p]+e[u].len;
      	SPFA(to);
      }
    }
    v[p]=0;
}

int main()
{
    n=get_int(),m=get_int();
    while(m--)
    {
      int tag=get_int(),x=get_int(),y=get_int(),z;
      if(tag==1) z=get_int(),build(x,y,-z);
      if(tag==2) z=get_int(),build(y,x,z);
      if(tag==3) build(x,y,0),build(y,x,0);
    }
    for(int i=1;i<=n;i++) build(0,i,0);
    memset(dis,0x3f,sizeof(dis)),dis[0]=0;
    SPFA(0);
    if(!flag) puts("Yes");
    else puts("No");
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值