种酸奶
问题描述
小 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≤a≤b≤n , ∣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;
}