小K 的农场(farm)题解

题目描述

小K 是个特么喜欢玩MC 的孩纸。。。
小K 在MC 里面建立很多很多的农场,总共n 个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m 个),以下列三种形式描述:
农场a 比农场b 至少多种植了c 个单位的作物,农场a 比农场b 至多多种植了c 个单位的作物,农场a 与农场b 种植的作物数一样多。但是,由于小K 的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。

输入

第一行包括两个整数n 和m,分别表示农场数目和小K 记忆中的信息的数目

接下来m 行:

如果每行的第一个数是1,接下来有三个整数a,b,c,表示农场a 比农场b 至少多种植了c 个单位的作物

如果每行第一个数是2,接下来有三个整数a,b,c,表示农场a 比农场b 至多多种植了c 个单位的作物

如果每行第一个数是3,接下来有两个整数a,b,表示农场a 种植的数量与b一样多

输出

如果存在某种情况与小K 的记忆吻合,输出“Yes” ,否则输出“No”

样例输入

3 3
3 1 2
1 1 3 1
2 2 3 2

样例输出

Yes

提示

【样例解释】三个农场种植的数量可以为(2,2,1)。

【数据范围与约定】

对于10%的数据,1 <= n ,m<= 10

对于100%的数据,1 <= n,m,a,b,c <= 10000

想法

  • 差分约束裸题。。

算法

  • 见代码

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#define MAXN 10005
#define INF ~0U>>2
using namespace std;
int n,m,opt,head[MAXN],tot,dist[MAXN],c[MAXN],x,y,z;
bool visit[MAXN],flag[MAXN],f,oka[MAXN];
struct Node
{
    int u,v,w,next;
}edge[MAXN<<2];
inline void add(int u,int v,int w)
{
    edge[tot].u=u,edge[tot].v=v,edge[tot].w=w,edge[tot].next=head[u],head[u]=tot++;
}
inline bool spfa(int s)
{
    queue<int >q;
    for (int i=1;i<=n;i++)
        dist[i]=INF;
    dist[s]=0;
    q.push(s);
    memset(visit,0,sizeof(visit));
    memset(c,0,sizeof(c));
    visit[s]=1;
    bool ok=true;
    while(!q.empty())
    {
        int x=q.front();q.pop();visit[x]=0;
        oka[x]=1;c[x]++;
        for (int i=head[x];i!=-1;i=edge[i].next)
        {
            int y=edge[i].v;
            if(dist[y]>dist[x]+edge[i].w)
            {
                dist[y]=dist[x]+edge[i].w;
                if(!visit[y])
                {
                    visit[y]=1;
                    q.push(y);
                    c[y]++;
                    if(c[y]>10)
                    {
                        return ok=false;
                    }
                }
            }
        }
    }
    return ok;
}
int main()
{
    //freopen("farm.in","r",stdin);
    //freopen("farm.out","w",stdout);
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&opt);
        if(opt==1)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,-z);
            flag[x]=flag[y]=1;
        }
        else if(opt==2)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(y,x,z);
            flag[x]=flag[y]=1;
        }
        else 
        {
            scanf("%d%d",&x,&y);
            add(x,y,0);
            add(y,x,0);
            flag[x]=flag[y]=1;
        }
    }
    f=1;
    for (int i=1;i<=n;i++)
    {
        if(flag[i]&&(!oka[i]))
            f&=spfa(i);
    }
    if(f)printf("Yes\n");
    else printf("No\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值