错题-种酸奶

种酸奶

问题描述

小 L 喜欢喝酸奶,春天来了,小 L 想把酸奶种在地里,等到来年春暖花开,就能长出好多好多酸奶了
n 个坑,小 L 给坑都编上号,从 1 号到 n 号,每个坑最多种一瓶酸奶。
但是有一些限制形如 k,a,b,c
k 等于 1 ,则第 a 号坑到第 b 号坑最多种 c 瓶酸奶。
k 等于 2 ,则第 a 号坑到第 b 号坑最少种 c 瓶酸奶。
k 等于 3 ,则第 a 号坑到第 b 号坑必须种少于 c 瓶酸奶。
k 等于 4 ,则第 a 号坑到第 b 号坑必须种多于 c 瓶酸奶。
k 等于 5 ,则第 a 号坑到第 b 号坑必须种等于 c 瓶酸奶。

问小 L 最多种多少瓶酸奶

输入格式

第一行两个整数 n,m ,表示有 n 个坑,有 m 条限制。
1≤n,m≤1000
接下来 m 行,每行四个整数 k,a,b,c
1≤k≤5 , 1≤abn , ∣c∣<=2000

输出格式

输出一行,若有解则输出一个整数,表示答案
否则输出 impossible

样例输入

5 5
1 1 4 4
2 2 5 1
3 2 4 2
4 1 5 2
5 1 3 2

样例输出

3

题解

这就是一道差分约束的题目,答案就是最后源点到每一个点的最短路径,这个路径就是其实就是前缀和

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

ll dis[1000000] = {0}; //这里的dis数组其实是代表的前缀和的意思,即到第i个坑最多能种多少个
ll cnt[1000000] = {0};
int vis[1000000] = {0};
ll head[10000] = {0};
struct bian
{
     ll v, w, next;
     bian() : v(0), w(0), next(-1) {}
} edge[10000];
ll total = 0;
void add(ll u, ll v, ll w)
{
     edge[total].v = v;
     edge[total].w = w;
     edge[total].next = head[u];
     head[u] = total;
     total++;
}
int main()
{
     ll n, m;
     cin >> n >> m;
     for(ll i = 0;i <= n;i ++)
     {
          head[i] = -1;
     }
     for (ll i = 0; i < m; i++)
     {
          ll k, a, b, c;
          cin >> k >> a >> b >> c;
          if (k == 1)
               add(a - 1, b, c);
          else if (k == 2)
               add(b, a - 1, -c);
          else if (k == 3)
               add(a - 1, b, c - 1);
          else if (k == 4)
               add(b, a - 1, -(c + 1));
          else
          {
               add(a - 1, b, c);
               add(b, a - 1, -c);
          }
     }

     // 由于每个坑最多种一瓶酸奶,因此还要加这个条件
     for (ll i = 1; i <= n; i++)
     {
          add(i - 1, i, 1);
          add(i, i - 1, 0);
     }

     //进行初始化
     for (ll i = 0; i <= n; i++)
     {
          dis[i] = 1e10;
     }

     //进行SPFA跑最短路
     queue<ll> q;
     q.push(0); //从0开始计算最短路,为什么不是从1呢,因为dis[1]的值可能是1/0,因为有可能在第一个坑里种或者不种
     dis[0] = 0;
     vis[0] = 1;
     while (q.size() != 0)
     {
          ll x = q.front();
          q.pop();
          vis[x] = 0;
          for (ll i = head[x]; i != -1; i = edge[i].next)
          {
               if (dis[edge[i].v] > dis[x] + edge[i].w)
               {
                    dis[edge[i].v] = dis[x] + edge[i].w;
                    cnt[edge[i].v]++;
                    if (cnt[edge[i].v] >= n)
                    {
                         cout << "impossible" << endl;
                         return 0;
                    }
                    if (vis[edge[i].v] == 0)
                    {
                         q.push(edge[i].v);
                         vis[edge[i].v] = 1;
                    }
               }
          }
     }
     cout << dis[n] << endl;
     return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值