差分约束系统
首先通过二分查找选择一个ans
然后测试这个ans是否能使得差分约束系统合法成立即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1001
#define INF 10000000
using namespace std;
int r[maxn], mk[maxn], t[maxn], qin[maxn], d[maxn], cnt, head[maxn];
struct node {
int v, w, nxt;
} nds[maxn * 4];
void insert(int u, int v, int w) {
nds[cnt].v = v, nds[cnt].w = w, nds[cnt].nxt = head[u];
head[u] = cnt++;
}
bool spfa() {
int i, cur, v, w;
for (i = 0; i <= 24; i++) {
qin[i] = 0, mk[i] = 0, d[i] = INF;
}
queue<int> q;
q.push(0);
qin[0] = 1, mk[0] = 1, d[0] = 0;
while (!q.empty()) {
cur = q.front();
q.pop();
qin[cur] = 0;
for (i = head[cur]; i != -1; i = nds[i].nxt) {
v = nds[i].v, w = nds[i].w;
if (d[v] > d[cur] + w) {
d[v] = d[cur] + w;
if (!qin[v]) {
qin[v] = 1;
mk[v]++;
if (mk[v] >= 25)return false;
q.push(v);
}
}
}
}
return true;
}
bool build(int ans) {
int i;
cnt = 0;
memset(head, -1, sizeof(head));
for (i = 1; i <= 24; i++) {
insert(i - 1, i, t[i]), insert(i, i - 1, 0);
}
for (i = 8; i <= 24; i++) {
insert(i, i - 8, -r[i]);
}
int l;
for (i = 1; i <= 7; i++) {
l = 16 + i;
// ans-d[l]+d[i]>=r[i] -> d[l]-d[i]<=ans-r[i]
insert(i, l, ans - r[i]);
}
//d[0]-d[24]=-ans -> d[0]-d[24]<=-ans && d[24]-d[0]<=ans
// 这条语句很重要,因为我们可以通过更改ans的值来判断这个差分约束系统是否合格
insert(24, 0, -ans);
insert(0, 24, ans);
return spfa();
}
int main() {
int T, i, n, x, ans;
scanf("%d", &T);
while (T--) {
memset(t, 0, sizeof(t));
for (i = 1; i <= 24; i++) {
scanf("%d", &r[i]);
}
scanf("%d", &n);
for (i = 1; i <= n; i++) {
scanf("%d", &x);
t[x + 1]++;
}
int le = 0, ri = n, mid;
ans = INF;
while (le <= ri) {
mid = (le + ri) >> 1;
if (build(mid)) {
ri = mid - 1;
ans = mid;
} else {
le = mid + 1;
}
}
if(ans==INF)puts("No Solution");
else printf("%d\n",ans);
}
}