BZOJ 3436 小K的农场 差分约束

Description

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

Input

   第一行包括两个整数n和m,分别表示农场数目和小K记忆中的信息的数目
接下来m行:
如果每行的第一个数是1,接下来有三个整数a,b,c,表示农场a比农场b至少多种植了c个单位的作物    如果每行第一个数是2,接下来有三个整数a,b,c,表示农场a比农场b至多多种植了c个单位的作物
如果每行第一个数是3,接下来有两个整数a,b,表示农场a种植的数量与b一样多输出格式

Output

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

Sample Input

33
312
1131
2232

Sample Output

Yes
样例解释

三个农场种植的数量可以为(2,2,1)。
对于100%的数据,1<=n,m,a,b,c<=10000
/**************************************************************
    Problem: 3436
    User: loi_francis
    Language: C++
    Result: Accepted
    Time:3656 ms
    Memory:5672 kb
****************************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxx = 100000;
int d[maxx], first[maxx], next[maxx << 1], tot, len[maxx];
bool used[maxx], flag;
queue <int> q;
int n, m, a, b, c;
struct edge
{
    int from, to, cost;
}es[maxx << 1];
void init()
{
    memset(d, 0x3f, sizeof(d));
    memset(first, -1, sizeof(first));
    memset(used, 0, sizeof(used));
    tot = 0;
}
void build(int ff, int tt, int dd)
{
    es[++tot] = (edge){ff, tt, dd};
    next[tot] = first[ff];
    first[ff] = tot;
}
void spfa(int s)
{
    d[s] = 0;
    q.push(s);
    used[s] = 1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        used[u] = 0;
        for(int i = first[u];i != -1;i = next[i])
        {
            int v = es[i].to;
            if(d[v] > d[u] + es[i].cost)
            {
                d[v] = d[u] + es[i].cost;
                len[v] = len[u] + 1;
                if(len[v] > n)
                {
                    flag = 1;
                    return ;
                }
                if(!used[v])
                {
                    q.push(v);
                    used[v] = 1;
                }
            }
        }
    }
}
int main()
{
    init();
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i ++)
    {
        int aa;
        scanf("%d", &aa);
        if(aa == 1)
        {
            scanf("%d%d%d", &a, &b, &c);
            build(a, b, -c);
        }
        if(aa == 2)
        {
            scanf("%d%d%d", &a, &b, &c);
            build(b, a, c);
        }
        if(aa == 3)
        {
            scanf("%d%d", &a, &b);
            build(a, b, 0);
            build(b, a, 0);
        }
    }
    for(int i = 1; i <= n; i ++)
    {
        spfa(i);
        if(flag)
        {
            cout<<"No";
            return 0;
        }
    }
    cout << "Yes";
    return 0;
}

 

上一篇
下一篇