constint N = 30, M = 300; int R[30], cap[N]; int h[N], cnt[N], dist[N], e[M], ne[M], w[M], idx; bool st[N]; int n;
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }
boolspfa(int S24){
memset(h, -1, sizeof h); idx = 0; for (int i = 1; i <= 24; i++) { add(i-1, i, 0); add(i, i-1, -cap[i]); if (i >= 8) add(i-8, i, R[i]); elseadd(i+16, i, R[i]-S24); } add(0, 24, S24), add(24, 0, -S24); memset(st, 0, sizeof st); memset(cnt, 0, sizeof cnt); memset(dist, -0x3f, sizeof dist); queue<int> q; q.push(0); dist[0] = 0; while (q.size()) { int t = q.front(); q.pop(); st[t] = false; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (dist[j] < dist[t] + w[i]) { dist[j] = dist[t] + w[i]; cnt[j] = cnt[t] + 1; if (cnt[j] >= 24) returnfalse; if (!st[j]) st[j] = true, q.push(j); } } } returntrue; }
intmain(){ int T; cin >> T; while (T--) { memset(cap, 0, sizeof cap); for (int i = 1; i <= 24; i++) cin >> R[i]; cin >> n; for (int i = 0; i < n; i++) { int t; cin >> t; cap[t+1]++; } // 枚举 S24 int l = 1, r = n; while (l < r) { int mid = l+r>>1; if (spfa(mid)) r=mid; else l=mid+1; } if (spfa(l)) cout << l << endl; else cout << "No Solution" << endl; } return0; }
[SCOI2011] 糖果
幼儿园里有 N 个小朋友,老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。
但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候, 老师需要满足小朋友们的 K 个要求。
constint N = 1e5+10, M = 2e5+10; int n, k; int h[N], e[M], ne[M], w[M], idx; bool st[N]; int dist[N], cnt[N];
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }
boolspfa(){ stack<int> q; for (int i = 1; i <= n; i++) { q.push(i); st[i] = true; dist[i] = 1; cnt[i] = 0; } int times = 0; while (q.size()) { int t = q.top(); q.pop(); st[t] = false; if (++times >= 3*n) returntrue; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (dist[j] < dist[t] + w[i]) { dist[j] = dist[t] + w[i]; cnt[j] = cnt[t] + 1; if (cnt[j] >= n) returntrue; if (!st[j]) q.push(j), st[j] = true; } } } returnfalse; }
intmain(){ scanf("%d%d", &n, &k); memset(h, -1, sizeof h); while (k--) { int x, a, b; scanf("%d%d%d", &x, &a, &b); if (x == 1) add(a, b, 0), add(b, a, 0); if (x == 2) add(a, b, 1); if (x == 3) add(b, a, 0); if (x == 4) add(b, a, 1); if (x == 5) add(a, b, 0); } if (spfa()) puts("-1"); else { longlong ans = 0; for (int i = 1; i <= n; i++) ans += dist[i]; printf("%lld\n", ans); } return0; }
[CF241E] Flights
给定 n 点 m 边无边权有向图,求是否存在方案,能够使得 1∼n 的所有路径的长度总和相同,并且对于每个边权都满足 1≤w≤2,如果可以输出 Yes 并按照输入的顺序输出 m 个边权,如果不可以输出 No。
constint N = 1010, M = 15010; int n, m, L[M], R[M]; int h[N], rh[N], e[M], ne[M], w[M], idx; int dist[N], cnt[N]; bool valid[N], rvalid[N], st[N]; #define va(u) (valid[u] && rvalid[u])
voidadd(int h[], int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }
voiddfs(int h[], bool st[], int u){ st[u] = true; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (!st[j]) dfs(h, st, j); } }
while (q.size()) { int t = q.front(); q.pop(); st[t] = false; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (!va(j)) continue; if (dist[j] > dist[t] + w[i]) { dist[j] = dist[t] + w[i]; cnt[j] = cnt[t] + 1; if (cnt[j] > n) returnfalse; if (!st[j]) q.push(j), st[j] = true; } } } returntrue; }
intmain(){ memset(h, -1, sizeof h); memset(rh, -1, sizeof rh); scanf("%d%d", &n, &m); for (int i = 0, a, b; i < m; i++) { scanf("%d%d", &a, &b); add(h, a, b, 2), add(rh, b, a, 0); L[i] = a, R[i] = b; } dfs(h, valid, 1), dfs(rh, rvalid, n); for (int i = 0; i < m; i++) add(h, R[i], L[i], -1); // 由于题目保证连通, 不用判连通性 if (!SPFA()) returnputs("No"), 0; puts("Yes"); for (int i = 0; i < m; i++) { if (va(L[i]) && va(R[i])) printf("%d\n", dist[R[i]] - dist[L[i]]); elseputs("1"); }
return0; }
[USACO05DEC] Layout G
正如其他物种一样,奶牛们也喜欢在排队打饭时与它们的朋友挨在一起。FJ 有编号为 1…N 的 N 头奶牛 (2≤N≤1000)。开始时,奶牛们按照编号顺序来排队。奶牛们很笨拙,因此可能有多头奶牛在同一位置上(即假设 i 号奶牛位于 Pi,则 P1≤P2≤⋯≤Pn)。
Byteasar 告诉你,所有参赛者的成绩都是整数秒。他还会为你提供了一些参赛者成绩的关系。具体是:他会给你一些数对 (A,B),表示 A 的成绩正好比 B 快 1 秒;他还会给你一些数对 (C,D),表示 C 的成绩不比 D 慢。而你要回答的是:所有参赛者最多能达到多少种不同的成绩,而不违背他给的条件。