种酸奶

问题描述

小 L 喜欢喝酸奶,春天来了,小 L 想把酸奶种在地里,等到来年春暖花开,就能长出好多好多酸奶了
nn 个坑,小 L 给坑都编上号,从 11 号到 nn 号,每个坑最多种一瓶酸奶。
但是有一些限制形如 k,a,b,ck,a,b,c
kk 等于 11 ,则第 aa 号坑到第 bb 号坑最多种 cc 瓶酸奶。
kk 等于 22 ,则第 aa 号坑到第 bb 号坑最少种 cc 瓶酸奶。
kk 等于 33 ,则第 aa 号坑到第 bb 号坑必须种少于 cc 瓶酸奶。
kk 等于 44 ,则第 aa 号坑到第 bb 号坑必须种多于 cc 瓶酸奶。
kk 等于 55 ,则第 aa 号坑到第 bb 号坑必须种等于 cc 瓶酸奶。

问小 L 最多种多少瓶酸奶

输入格式

第一行两个整数 n,mn,m ,表示有 nn 个坑,有 mm 条限制。
1n,m10001\le n,m\le1000
接下来 mm 行,每行四个整数 k,a,b,ck,a,b,c
1k51\le k\le 51abn1\le a\le b\le n , c<=2000|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;
#define MAXN 1000000
typedef long long ll;
int n, m;
int k, a, b, c;

struct edge {
    int u, v, w, next;  //入点、出点、边权、下一条边的编号
    bool operator<(const edge& e) const {
        return w < e.w;
    }
} edges[MAXN];

int tot = 0;                 //当前边的总数
vector<int> head(MAXN, -1);  //储存每个节点的第一条边的编号,-1表示没有边

void addEdge(int u, int v, int w) {  //加一条边
    edges[tot].u = u, edges[tot].v = v, edges[tot].next = head[u], edges[tot].w = w;
    head[u] = tot++;
}
int dis[MAXN], vis[MAXN], cnt[MAXN];

bool spfa(int s) {
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    memset(cnt, 0, sizeof(cnt));
    queue<int> q;
    // dis[0] = 0;
    dis[s] = 0;
    q.push(s);
    vis[s] = 1;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for (int i = head[u]; i != -1; i = edges[i].next) {
            int v = edges[i].v;
            if (dis[v] > dis[u] + edges[i].w) {
                dis[v] = dis[u] + edges[i].w;
                cnt[v] = cnt[u] + 1;
                if (cnt[v] >= n)
                    return false;  //有负环
                if (!vis[v]) {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }  // 1、3、5可达但是这里没有让他们连起来

    return true;
}

int main() {
    // freopen("a.in", "r", stdin);
    // freopen("a.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        scanf("%d%d%d%d", &k, &a, &b, &c);

        if (k == 1) {  //<=
            addEdge(a - 1, b, c);
        } else if (k == 2) {  //>=
            addEdge(b, a - 1, -c);
        } else if (k == 3) {  //<
            addEdge(a - 1, b, c - 1);
        } else if (k == 4) {  //>
            addEdge(b, a - 1, -c - 1);
        } else if (k == 5) {  //=
            addEdge(a - 1, b, c);
            addEdge(b, a - 1, -c);
        }
    }
    for (int i = 1; i <= n; ++i) {
        addEdge(i - 1, i, 1);
        addEdge(i, i - 1, 0);
    }
    if (spfa(0)) {
        printf("%d", dis[n]);
    } else {
        printf("impossible");
    }

    return 0;
}