问题描述
小 L 喜欢喝酸奶,春天来了,小 L 想把酸奶种在地里,等到来年春暖花开,就能长出好多好多酸奶了
有 个坑,小 L 给坑都编上号,从 号到 号,每个坑最多种一瓶酸奶。
但是有一些限制形如 。
若 等于 ,则第 号坑到第 号坑最多种 瓶酸奶。
若 等于 ,则第 号坑到第 号坑最少种 瓶酸奶。
若 等于 ,则第 号坑到第 号坑必须种少于 瓶酸奶。
若 等于 ,则第 号坑到第 号坑必须种多于 瓶酸奶。
若 等于 ,则第 号坑到第 号坑必须种等于 瓶酸奶。
问小 L 最多种多少瓶酸奶
输入格式
第一行两个整数 ,表示有 个坑,有 条限制。
接下来 行,每行四个整数
, ,
输出格式
输出一行,若有解则输出一个整数,表示答案
否则输出 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;
}