记 f(i,j) f ( i , j ) 表示第 i i 个人当前血量为 j j 的概率,那么每次锁定操作就是做一次背包。
对于结界操作,我们需要对每个人 i i 处理出其他人有 j j 个存活的概率,注意到这个dp是可逆的,所以求出总的之后暴力进行多项式除法即可。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 205;
const int mod = 998244353;
int n, m, q, a[N], b[N], t[N], inv[N], f[N][N], g[N][N];
inline int Qow(int x, int y) {
int r = 1;
for (; y; y >>= 1, x = 1LL * x * x % mod) {
if (y & 1) {
r = 1LL * r * x % mod;
}
}
return r;
}
inline void Modify(int p, int v) {
f[p][0] = (1LL * f[p][1] * v + f[p][0]) % mod;
for (int i = 1; i <= a[p]; ++i) {
f[p][i] = (1LL * f[p][i + 1] * v + 1LL * f[p][i] * (mod + 1 - v)) % mod;
}
}
inline void Query() {
Read(q), g[0][0] = 1;
for (int i = 1; i <= q; ++i) {
Read(b[i]);
g[i][0] = 1LL * g[i - 1][0] * f[b[i]][0] % mod;
for (int j = 1; j <= i; ++j) {
g[i][j] = (1LL * g[i - 1][j] * f[b[i]][0] + 1LL * g[i - 1][j - 1] * (mod + 1 - f[b[i]][0])) % mod;
}
}
for (int i = 1; i <= q; ++i) {
int ans = 0;
if (f[i][0] != 1) {
for (int j = 0; j <= q; ++j) {
t[j] = g[q][j];
}
int v = Qow(mod + 1 - f[b[i]][0], mod - 2);
for (int j = q; j; --j) {
int pro = 1LL * t[j] * v % mod;
ans = (1LL * pro * (mod + 1 - f[b[i]][0]) % mod * inv[j] + ans) % mod;
t[j - 1] = (t[j - 1] - 1LL * pro * f[b[i]][0] % mod + mod) % mod;
}
}
printf("%d%c", ans, i == q ? '\n' : ' ');
}
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n);
for (int i = 1; i <= n; ++i) {
inv[i] = Qow(i, mod - 2);
Read(a[i]), f[i][a[i]] = 1;
}
Read(m);
for (int i = 1, o; i <= m; ++i) {
Read(o);
if (!o) {
int x, p, q;
Read(x), Read(p), Read(q);
Modify(x, 1LL * p * Qow(q, mod - 2) % mod);
} else {
Query();
}
}
for (int i = 1; i <= n; ++i) {
int r = 0;
for (int j = 1; j <= a[i]; ++j) {
r = (1LL * f[i][j] * j + r) % mod;
}
printf("%d%c", r, i == n ? '\n' : ' ');
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
dep(x)+dep(y)−dep(lca(x,y))−dep′(lca′(x,y))=dis(x,y)+dis′(x,y)+dep(x)−dep′(x)+dep(y)−dep′(y)2 d e p ( x ) + d e p ( y ) − d e p ( l c a ( x , y ) ) − d e p ′ ( l c a ′ ( x , y ) ) = d i s ( x , y ) + d i s ′ ( x , y ) + d e p ( x ) − d e p ′ ( x ) + d e p ( y ) − d e p ′ ( y ) 2
对第二棵树点分,在第一棵树上建立虚树跑一下树DP就行了。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 366670;
const int M = 20;
const LL inf = 1LL << 60;
int n, m, top, bel[N], siz[N], sta[N], seq[N << 1];
vector <int> adj[N];
LL ans, len[N];
bool vis[N];
struct Info {
int c;
LL w;
Info(int c = 0, LL w = -inf):c(c), w(w) {}
bool operator < (const Info &b) const {
return w > b.w;
}
} val[N][2];
struct Tree {
struct Edge {
int p, v;
LL w;
Edge(int p = 0, int v = 0, LL w = 0):p(p), v(v), w(w) {}
} e[N << 1];
int cnt, tim, l[N], p[N], q[N], dep[N], hed[N], par[N], f[M][N];
LL dis[N];
inline void AddEdge(int x, int y, LL w) {
e[++cnt] = Edge(y, hed[x], w), hed[x] = cnt;
e[++cnt] = Edge(x, hed[y], w), hed[y] = cnt;
}
inline int Min(int x, int y) {
return dep[x] < dep[y] ? x : y;
}
inline void DFS(int x) {
p[x] = ++tim, f[0][tim] = x;
for (int i = hed[x]; i; i = e[i].v) {
int y = e[i].p;
if (y != par[x]) {
par[y] = x, dep[y] = dep[x] + 1, dis[y] = dis[x] + e[i].w, DFS(y);
}
}
q[x] = tim;
}
inline int LCA(int x, int y) {
if (p[x] > p[y]) {
swap(x, y);
}
if (q[x] >= q[y]) {
return x;
}
int k = l[p[y] - p[x] + 1];
return par[Min(f[k][p[x]], f[k][p[y] - (1 << k) + 1])];
}
inline void Build() {
DFS(1);
for (int i = 1; i < M; ++i) {
for (int j = 1; j + (1 << i) - 1 <= n; ++j) {
f[i][j] = Min(f[i - 1][j], f[i - 1][j + (1 << i - 1)]);
}
}
for (int i = 2; i <= n; ++i) {
l[i] = l[i >> 1] + 1;
}
}
inline void FindRoot(int x, int p, int s, int &c) {
bool f = true;
siz[x] = 1;
for (int i = hed[x]; i; i = e[i].v) {
int y = e[i].p;
if (!vis[y] && y != p) {
FindRoot(y, x, s, c), siz[x] += siz[y], f &= siz[y] <= s >> 1;
}
}
f &= siz[x] >= s >> 1;
if (f) {
c = x;
}
}
inline void DFS(int x, int p, int b, LL d) {
siz[x] = 1, seq[++m] = x, bel[x] = b, len[x] = d;
for (int i = hed[x]; i; i = e[i].v) {
int y = e[i].p;
if (!vis[y] && y != p) {
DFS(y, x, b, d + e[i].w), siz[x] += siz[y];
}
}
}
inline void DP(int x) {
val[x][0] = val[x][1] = Info();
if (bel[x]) {
val[x][0] = Info(bel[x], len[x] + dis[x]);
}
for (auto y : adj[x]) {
DP(y);
for (int i = 0; i < 2; ++i) {
if (val[x][i].c) {
for (int j = 0; j < 2; ++j) {
if (val[y][j].c && val[y][j].c != val[x][i].c) {
CheckMax(ans, val[x][i].w + val[y][j].w - (dis[x] << 1));
}
}
}
}
Info tmp[4];
tmp[0] = val[x][0], tmp[1] = val[x][1], tmp[2] = val[y][0], tmp[3] = val[y][1];
sort(tmp, tmp + 4);
val[x][0] = tmp[0], val[x][1] = Info();
for (int i = 1; i < 4; ++i) {
if (tmp[i].c && tmp[i].c != tmp[0].c) {
val[x][1] = tmp[i];
break;
}
}
}
}
inline void Solve() {
sort(seq + 1, seq + m + 1, [&](const int &x, const int &y) {
return p[x] < p[y];
});
for (int i = m; i > 1; --i) {
seq[++m] = LCA(seq[i], seq[i - 1]);
}
sort(seq + 1, seq + m + 1, [&](const int &x, const int &y) {
return p[x] < p[y];
});
m = unique(seq + 1, seq + m + 1) - seq - 1, top = 0;
for (int i = 1; i <= m; ++i) {
for (; top && !(p[sta[top]] <= p[seq[i]] && q[sta[top]] >= q[seq[i]]); --top);
if (top) {
adj[sta[top]].pb(seq[i]);
}
sta[++top] = seq[i];
}
DP(seq[1]);
for (int i = 1; i <= m; ++i) {
adj[seq[i]].clear(), bel[seq[i]] = 0;
}
}
} A, B;
inline void Solve() {
for (int i = 1; i <= m; ++i) {
len[seq[i]] += A.dis[seq[i]] - B.dis[seq[i]];
}
A.Solve();
}
inline void Solve(int x, int s) {
int c;
B.FindRoot(x, 0, s, c);
vis[x = c] = true, seq[m = 1] = x, bel[x] = x, len[x] = 0;
for (int i = B.hed[x]; i; i = B.e[i].v) {
int y = B.e[i].p;
if (!vis[y]) {
B.DFS(y, x, y, B.e[i].w);
}
}
Solve();
for (int i = B.hed[x]; i; i = B.e[i].v) {
int y = B.e[i].p;
if (!vis[y]) {
Solve(y, siz[y]);
}
}
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n);
for (int i = 1; i < n; ++i) {
int x, y;
LL w;
Read(x), Read(y), Read(w);
A.AddEdge(x, y, w);
}
for (int i = 1; i < n; ++i) {
int x, y;
LL w;
Read(x), Read(y), Read(w);
B.AddEdge(x, y, w);
}
A.Build(), B.Build(), Solve(1, n);
for (int i = 1; i <= n; ++i) {
CheckMax(ans, A.dis[i] - B.dis[i] << 1);
}
printf("%lld\n", ans >> 1);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
注意到区间之间一定是包含或者相离,不然无解。这样可以建出树结构,记 f(n) f ( n ) 表示满足 Li=1(i≠n+1) L i = 1 ( i ≠ n + 1 ) 的排列个数, soni s o n i 表示 i i 的儿子个数,那么答案就是 ∏f(soni) ∏ f ( s o n i ) 。
考虑如何求 f(n) f ( n ) ,由于问题的对称性,可以将下标与值互换,变成询问有多少个排列任意一个长度不为 1 1 的连续区间都经过最大值。
考虑删除 1 1 这个值,如果剩下的序列合法,那么就是在 f(n−1) f ( n − 1 ) 插入一个与 2 2 不相邻的数,方案数是 n−1 n − 1 。
另一种情况,考虑生成的一个极长连续段,假设它的值域为 [x,x+l−1] [ x , x + l − 1 ] ,那么一定有 x>2,x+l−1<n+1 x > 2 , x + l − 1 < n + 1 ,那么选取 x x 的方案数就是 n−l−1 n − l − 1 ,而这一段内部排列的方案数是 f(l) f ( l ) (将最大最小对称一下),将这一段看成整体,外部的方案数是 f(n−l) f ( n − l ) ,所以有递推式:
f(n)=(n−1)f(n−1)+∑n−2i=2(i−1)f(i)f(n−i) f ( n ) = ( n − 1 ) f ( n − 1 ) + ∑ i = 2 n − 2 ( i − 1 ) f ( i ) f ( n − i )
分治NTT优化即可。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 131075;
const int M = 20;
const int G = 3;
const int mod = 998244353;
int D, L, W[M], R[N];
inline int Qow(int x, int y) {
int r = 1;
for (; y; y >>= 1, x = 1LL * x * x % mod) {
if (y & 1) {
r = 1LL * r * x % mod;
}
}
return r;
}
inline void DFT(int *a) {
for (int i = 0; i < D; ++i) {
if (i < R[i]) {
swap(a[i], a[R[i]]);
}
}
for (int i = 1, l = L - 1; i < D; i <<= 1, --l) {
for (int j = 0; j < D; j += i << 1) {
for (int k = 0, w = 1, u, v; k < i; ++k, w = 1LL * w * W[l] % mod) {
u = a[j + k], v = 1LL * w * a[j + k + i] % mod;
a[j + k] = (u + v) % mod, a[j + k + i] = (u - v + mod) % mod;
}
}
}
}
inline vector <int> Mul(vector <int> a, vector <int> b) {
static int x[N], y[N];
int n = a.size(), m = b.size();
for (D = 1, L = 0; D < n + m - 1; D <<= 1, ++L);
for (int i = 1; i < D; ++i) {
R[i] = (R[i >> 1] >> 1) | ((i & 1) << L - 1);
}
W[0] = Qow(G, mod - 1 >> L);
for (int i = 1; i < L; ++i) {
W[i] = 1LL * W[i - 1] * W[i - 1] % mod;
}
for (int i = 0; i < D; ++i) {
x[i] = i < n ? a[i] : 0, y[i] = i < m ? b[i] : 0;
}
DFT(x), DFT(y);
for (int i = 0; i < D; ++i) {
x[i] = 1LL * x[i] * y[i] % mod;
}
W[0] = Qow(W[0], mod - 2);
for (int i = 1; i < L; ++i) {
W[i] = 1LL * W[i - 1] * W[i - 1] % mod;
}
DFT(x);
for (int i = 0, v = Qow(D, mod - 2); i < D; ++i) {
x[i] = 1LL * x[i] * v % mod;
}
return vector <int> (x, x + n + m - 1);
}
int n, ans, top, a[N], b[N], f[N], sta[N];
inline void Solve(int l, int r) {
if (l == r) {
f[l] = (1LL * f[l - 1] * (l - 1) + f[l]) % mod;
return ;
}
int mid = l + r >> 1;
Solve(l, mid);
vector <int> a, b;
for (int i = l; i <= mid; ++i) {
a.pb(f[i]), b.pb(1LL * f[i] * (i - 1) % mod);
}
a = Mul(a, b);
for (int i = max(mid + 1, l << 1); i <= r; ++i) {
f[i] = (f[i] + a[i - (l << 1)]) % mod;
}
if (l != 2) {
a.clear(), b.clear();
for (int i = 2; i <= min(l - 1, r - l); ++i) {
a.pb(f[i]);
}
for (int i = l; i <= mid; ++i) {
b.pb(f[i]);
}
a = Mul(a, b);
for (int i = max(l + 2, mid + 1); i <= r; ++i) {
f[i] = (1LL * a[i - l - 2] * (i - 2) + f[i]) % mod;
}
}
Solve(mid + 1, r);
}
int Main() {
for (int i = 1; i <= n; ++i) {
Read(a[i]), b[i] = 0;
}
if (a[n] != n) {
puts("0");
return 0;
}
ans = 1, top = 0;
for (int i = n; ~i; --i) {
for (; top && sta[top] - a[sta[top]] >= i; ++b[sta[--top]]);
if (top && sta[top] - a[sta[top]] > i - a[i]) {
puts("0");
return 0;
}
sta[++top] = i;
}
for (int i = 1; i <= n; ++i) {
ans = 1LL * ans * f[b[i]] % mod;
}
printf("%d\n", ans);
return 0;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
for (Read(T), Read(n), f[0] = 1, f[1] = 2, Solve(2, n - 1); T; --T) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
将所有果汁按照 d d 从大到小排序,对于每次询问二分,那么剩下的部分就可以贪心选取了,用主席树维护即可。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 100005;
const int M = 6000005;
struct Info {
int d, p, l;
bool operator < (const Info &b) const {
return d > b.d;
}
} a[N];
struct Node {
int l, r;
LL v, s;
} e[M];
int n, m, mxp, tot, rot[N];
inline void Modify(int &x, int y, int l, int r, int p, int v) {
e[x = ++tot] = e[y], e[x].v += v, e[x].s += 1LL * p * v;
if (l == r) {
return ;
}
int mid = l + r >> 1;
if (p <= mid) {
Modify(e[x].l, e[y].l, l, mid, p, v);
} else {
Modify(e[x].r, e[y].r, mid + 1, r, p, v);
}
}
inline bool Check(int x, int l, int r, LL vol, LL pri) {
if (e[x].v < vol || pri / l < vol) {
return false;
}
if (l == r) {
return true;
}
int mid = l + r >> 1;
if (vol <= e[e[x].l].v) {
return Check(e[x].l, l, mid, vol, pri);
} else {
return Check(e[x].r, mid + 1, r, vol - e[e[x].l].v, pri - e[e[x].l].s);
}
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m);
for (int i = 1; i <= n; ++i) {
Read(a[i].d), Read(a[i].p), Read(a[i].l);
CheckMax(mxp, a[i].p);
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; ++i) {
Modify(rot[i], rot[i - 1], 1, mxp, a[i].p, a[i].l);
}
for (int i = 1; i <= m; ++i) {
LL pri, vol;
Read(pri), Read(vol);
if (!Check(rot[n], 1, mxp, vol, pri)) {
puts("-1");
} else {
int l = 1, r = n - 1, ret = n;
while (l <= r) {
int mid = l + r >> 1;
if (Check(rot[mid], 1, mxp, vol, pri)) {
ret = mid, r = mid - 1;
} else {
l = mid + 1;
}
}
printf("%d\n", a[ret].d);
}
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
做法是假的
记 f(i) f ( i ) 表示 i i 是逗号,其子树最小值最大可以是多少,暴力转移就行了,常数很小可以通过,具体细节参考代码。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return b < a ? a = b, true : false;
}
const int N = 405;
vector <int> adj[N];
string inf, f[N];
char s[N];
int n, m;
bool operator < (const string &a, const string &b) {
return a.length() != b.length() ? a.length() < b.length() : b > a;
}
inline string Leq(string s, string t) {
if (s[0] == '0' || s.length() > t.length()) {
return "";
}
if (s.length() < t.length()) {
for (int i = 0; i < s.length(); ++i) {
if (s[i] == '?') {
s[i] = '9';
}
}
return s;
}
string x = "x", y = "y";
for (int i = 0; i < s.length(); ++i) {
if (s[i] != '?') {
if (s[i] < t[i]) {
x = max(x, y) + s[i], y = "x";
} else if (s[i] == t[i]) {
x += s[i], y += s[i];
} else {
x += s[i], y = "x";
}
} else {
x += "9";
if (t[i] != '0') {
CheckMax(x, y + (char)(t[i] - 1));
}
y += t[i];
}
}
if (x[0] == 'x' || x[1] == '0') {
return "";
}
x.erase(x.begin());
return x;
}
inline string Geq(string s, string t) {
if (s[0] == '0' || s.length() < t.length()) {
return "";
}
if (s.length() > t.length()) {
for (int i = 0; i < s.length(); ++i) {
if (s[i] == '?') {
s[i] = i ? '0' : '1';
}
}
return s;
}
string x = "y", y = "x";
for (int i = 0; i < s.length(); ++i) {
if (s[i] != '?') {
if (s[i] > t[i]) {
x = (y > x ? x : y) + s[i], y = "y";
} else if (s[i] == t[i]) {
x += s[i], y += s[i];
} else {
x += s[i], y = "y";
}
} else {
x += "0";
if (t[i] != '9') {
if (x > y + (char)(t[i] + 1)) {
x = y + (char)(t[i] + 1);
}
}
y += t[i];
}
}
if (x[0] == 'y' || x[1] == '0') {
return "";
}
x.erase(x.begin());
return x;
}
inline string U(int x, string str) {
string ans = "";
if (str != "" && f[x] != "") {
ans = Leq(str, f[x]);
}
if (s[x] != ',') {
str += s[x];
string ret = inf;
for (auto y : adj[x]) {
CheckMin(ret, U(y, str));
}
CheckMax(ans, ret);
}
return ans;
}
inline void U(int x) {
if (x > n) {
return ;
}
for (auto y : adj[x]) {
U(y);
}
if (!isdigit(s[x])) {
f[x] = inf;
for (auto y : adj[x]) {
CheckMin(f[x], U(y, ""));
}
}
}
inline bool C(int x, string str, string lst) {
if (str != "" && str[0] == '0') {
return false;
}
if (f[x] != "") {
string tmp = Geq(str, lst);
if (tmp != "" && tmp < f[x]) {
return true;
}
}
if (s[x] == ',') {
return false;
}
str += s[x];
for (auto y : adj[x]) {
if (!C(y, str, lst)) {
return false;
}
}
return true;
}
inline void D(int x, string str, string lst) {
if (x > n) {
return ;
}
if (s[x] == '?') {
if (lst < str && str < f[x]) {
s[x] = ',';
} else {
for (s[x] = '0'; !C(x, str, lst); ++s[x]);
}
}
if (s[x] == ',') {
lst = str, str = "";
} else {
str += s[x];
}
for (auto y : adj[x]) {
D(y, str, lst);
}
}
int Main() {
scanf("%s", s + 1), n = strlen(s + 1), m = n, inf = "";
for (int i = 0; i <= n; ++i) {
adj[i].clear(), f[i] = "", inf += "9";
}
s[0] = ',';
for (int i = 1, x; i <= n; ++i) {
Read(x), adj[x].pb(i);
}
for (int i = 1; i <= n; ++i) {
if (adj[i].empty()) {
adj[i].pb(++m), s[m] = ',', f[m] = inf;
}
}
U(0);
if (f[0] == "") {
puts("failed");
return 0;
}
D(0, "", "0");
for (int i = 1; i <= n; ++i) {
putchar(s[i]);
}
putchar(10);
return 0;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
for (Read(T); T; --T) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
爆搜。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int inf = 0x3f3f3f3f;
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
inline void Update() {
int ret = 0;
for (int i = 0; i < n; ++i) {
ret += run[i][per[i]];
}
for (int i = 0; i < n; ++i) {
for (auto j : adj[i]) {
ret += mov[per[i]][per[j]];
}
}
if (CheckMin(ans, ret)) {
bes = per;
}
}
inline void DFS(int x) {
if (x == n) {
Update();
return ;
}
for (per[x] = 0; per[x] < m; DFS(x + 1), ++per[x]);
}
int main() {
freopen("placement1.in", "r", stdin);
freopen("placement1.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n), ans = inf, DFS(0);
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
爆搜。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int inf = 0x3f3f3f3f;
struct Event {
int o, v, t;
Event(int o = 0, int v = 0, int t = 0):o(o), v(v), t(t) {}
bool operator < (const Event &b) const {
return t > b.t;
}
};
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
inline void Update() {
vector int , vector <int>, greater <int>>> que(m);
priority_queue q;
vector <bool> cur(m);
vector <int> deg(n);
int ret = 0;
for (int i = 0; i < n; ++i) {
for (auto j : adj[i]) {
++deg[j];
}
}
for (int i = 0; i < n; ++i) {
if (!deg[i]) {
if (!cur[per[i]]) {
cur[per[i]] = true, q.push(Event(1, i, run[i][per[i]] + ret));
} else {
que[per[i]].push(i);
}
}
}
while (!q.empty()) {
Event e = q.top();
q.pop();
int x = e.v;
ret = e.t;
if (e.o) {
for (auto y : adj[x]) {
q.push(Event(0, y, ret + mov[per[x]][per[y]]));
}
cur[per[x]] = false;
if (!que[per[x]].empty()) {
int i = que[per[x]].top();
que[per[x]].pop();
cur[per[x]] = true, q.push(Event(1, i, run[i][per[i]] + ret));
}
} else {
if (!--deg[x]) {
if (!cur[per[x]]) {
cur[per[x]] = true, q.push(Event(1, x, run[x][per[x]] + ret));
} else {
que[per[x]].push(x);
}
}
}
}
if (CheckMin(ans, ret)) {
bes = per;
}
}
inline void DFS(int x) {
if (x == n) {
Update();
return ;
}
for (per[x] = 0; per[x] < m; DFS(x + 1), ++per[x]);
}
int main() {
freopen("placement2.in", "r", stdin);
freopen("placement2.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n), ans = inf, DFS(0);
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
背包dp。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 110;
const int lim = 106;
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
int f[N][N][N][N];
int main() {
freopen("placement3.in", "r", stdin);
freopen("placement3.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
f[0][0][0][0] = 1, per.resize(n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= lim; ++j) {
for (int k = 0; k <= lim; ++k) {
for (int l = 0; l <= lim; ++l) {
if (f[i][j][k][l]) {
if (j + run[i][0] <= lim) {
f[i + 1][j + run[i][0]][k][l] = 1;
}
if (k + run[i][1] <= lim) {
f[i + 1][j][k + run[i][1]][l] = 2;
}
if (l + run[i][2] <= lim) {
f[i + 1][j][k][l + run[i][2]] = 3;
}
}
}
}
}
}
for (int i = 0; i <= lim; ++i) {
for (int j = 0; j <= lim; ++j) {
for (int k = 0; k <= lim; ++k) {
if (f[n][i][j][k]) {
ans = lim;
for (int t = n - 1; ~t; --t) {
per[t] = f[t + 1][i][j][k] - 1;
if (f[t + 1][i][j][k] == 1) {
i -= run[t][0];
} else if (f[t + 1][i][j][k] == 2) {
j -= run[t][1];
} else {
k -= run[t][2];
}
}
i = j = k = lim;
}
}
}
}
bes = per;
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
对三条链分别dp。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 400;
const int inf = 0x3f3f3f3f;
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
int f[N][N], g[N][N];
inline void Solve(int l, int r) {
for (int i = 0; i < m; ++i) {
f[l][i] = run[l][i];
}
for (int i = l + 1; i < r; ++i) {
for (int j = 0; j < m; ++j) {
f[i][j] = inf;
for (int k = 0; k < m; ++k) {
if (CheckMin(f[i][j], f[i - 1][k] + mov[k][j])) {
g[i][j] = k;
}
}
f[i][j] += run[i][j];
}
}
int pos = -1, ret = inf;
for (int i = 0; i < m; ++i) {
if (CheckMin(ret, f[r - 1][i])) {
pos = i;
}
}
ans += ret;
for (int i = r - 1; i >= l; --i) {
per[i] = pos, pos = g[i][pos];
}
}
int main() {
freopen("placement4.in", "r", stdin);
freopen("placement4.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n), Solve(0, 133), Solve(133, 266), Solve(266, 399), bes = per;
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
状压dp。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 3125;
const int inf = 0x3f3f3f3f;
const int base[] = {1, 5, 25, 125, 625, 3125};
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
int f[N][N], g[N][N];
int main() {
freopen("placement5.in", "r", stdin);
freopen("placement5.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[y].pb(x);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n);
for (int i = 0; i < N; ++i) {
for (int j = 0; j < m; ++j) {
f[4][i] += run[4 - j][i / base[j] % m];
for (auto k : adj[4 - j]) {
f[4][i] += mov[i / base[4 - k] % m][i / base[j] % m];
}
}
}
for (int i = 5; i < n; ++i) {
for (int j = 0; j < N; ++j) {
f[i][j] = inf;
}
}
for (int i = 4; i < n - 1; ++i) {
for (int j = 0; j < N; ++j) {
for (int k = 0; k < m; ++k) {
int ret = f[i][j] + run[i + 1][k], l = j % base[m - 1] * m + k;
for (auto x : adj[i + 1]) {
ret += mov[j / base[i - x] % m][k];
}
if (CheckMin(f[i + 1][l], ret)) {
g[i + 1][l] = j;
}
}
}
}
ans = inf;
int cur = -1;
for (int i = 0; i < N; ++i) {
if (CheckMin(ans, f[n - 1][i])) {
cur = i;
}
}
for (int i = n - 1; i > 4; --i) {
per[i] = cur % m, cur = g[i][cur];
}
for (int i = 0; i < m; ++i) {
per[4 - i] = cur / base[i] % m;
}
bes = per;
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
最小割。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 505;
const int M = 100005;
const int inf = 0x3f3f3f3f;
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
struct Edge {
int p, v, w;
Edge(int p = 0, int v = 0, int w = 0):p(p), v(v), w(w) {}
} e[M];
int S, T, cnt = 1, cur[N], dis[N], hed[N];
inline void AddEdge(int x, int y, int w) {
e[++cnt] = Edge(y, hed[x], w), hed[x] = cnt;
e[++cnt] = Edge(x, hed[y], 0), hed[y] = cnt;
}
inline bool BFS() {
queue <int> q;
for (int i = S; i <= T; ++i) {
dis[i] = 0;
}
for (q.push(S), dis[S] = 1; !q.empty(); q.pop()) {
int x = q.front();
for (int i = hed[x]; i; i = e[i].v) {
if (e[i].w && !dis[e[i].p]) {
dis[e[i].p] = dis[x] + 1, q.push(e[i].p);
}
}
}
return dis[T];
}
inline int DFS(int x, int f) {
if (x == T) {
return f;
}
int r = 0, w;
for (int &i = cur[x]; i; i = e[i].v) {
if (e[i].w && dis[e[i].p] == dis[x] + 1) {
w = DFS(e[i].p, min(f - r, e[i].w));
e[i].w -= w, e[i ^ 1].w += w, r += w;
if (r == f) {
return r;
}
}
}
dis[x] = -1;
return r;
}
inline int Dinic() {
int r = 0;
while (BFS()) {
for (int i = S; i <= T; ++i) {
cur[i] = hed[i];
}
r += DFS(S, inf);
}
return r;
}
int main() {
freopen("placement6.in", "r", stdin);
freopen("placement6.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n), T = n + 1;
for (int i = 0; i < n; ++i) {
AddEdge(S, i + 1, run[i][0]), AddEdge(i + 1, T, run[i][1]);
}
for (int i = 0; i < n; ++i) {
for (auto j : adj[i]) {
AddEdge(i + 1, j + 1, mov[1][0]), AddEdge(j + 1, i + 1, mov[0][1]);
}
}
ans = Dinic();
for (int i = 0; i < n; ++i) {
per[i] = dis[i + 1] == 2;
}
bes = per;
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
二分图匹配。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 1105;
const int M = 100005;
const int lim = 1014;
const int inf = 0x3f3f3f3f;
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
struct Edge {
int p, v, w;
Edge(int p = 0, int v = 0, int w = 0):p(p), v(v), w(w) {}
} e[M];
int S, T, cnt = 1, cur[N], dis[N], hed[N], edg[N][N];
inline void AddEdge(int x, int y, int w) {
e[++cnt] = Edge(y, hed[x], w), hed[x] = cnt;
e[++cnt] = Edge(x, hed[y], 0), hed[y] = cnt;
}
inline bool BFS() {
queue <int> q;
for (int i = S; i <= T; ++i) {
dis[i] = 0;
}
for (q.push(S), dis[S] = 1; !q.empty(); q.pop()) {
int x = q.front();
for (int i = hed[x]; i; i = e[i].v) {
if (e[i].w && !dis[e[i].p]) {
dis[e[i].p] = dis[x] + 1, q.push(e[i].p);
}
}
}
return dis[T];
}
inline int DFS(int x, int f) {
if (x == T) {
return f;
}
int r = 0, w;
for (int &i = cur[x]; i; i = e[i].v) {
if (e[i].w && dis[e[i].p] == dis[x] + 1) {
w = DFS(e[i].p, min(f - r, e[i].w));
e[i].w -= w, e[i ^ 1].w += w, r += w;
if (r == f) {
return r;
}
}
}
dis[x] = -1;
return r;
}
inline int Dinic() {
int r = 0;
while (BFS()) {
for (int i = S; i <= T; ++i) {
cur[i] = hed[i];
}
r += DFS(S, inf);
}
return r;
}
int main() {
freopen("placement7.in", "r", stdin);
freopen("placement7.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n), T = n + m + 1;
for (int i = 0; i < n; ++i) {
AddEdge(S, i + 1, 1);
}
for (int i = 0; i < m; ++i) {
AddEdge(i + n + 1, T, 1);
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (run[i][j] <= lim) {
AddEdge(i + 1, j + n + 1, 1), edg[i][j] = cnt;
}
}
}
if (Dinic() == n) {
ans = lim;
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (run[i][j] <= lim && e[edg[i][j]].w) {
per[i] = j;
break;
}
}
}
bes = per;
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
分层图,对于每层二分答案之后就是二分图匹配了。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 655;
const int M = 100005;
const int inf = 0x3f3f3f3f;
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
struct Edge {
int p, v, w;
Edge(int p = 0, int v = 0, int w = 0):p(p), v(v), w(w) {}
} e[M];
int S, T, cnt = 1, cur[N], dis[N], hed[N], edg[N][N];
inline void AddEdge(int x, int y, int w) {
e[++cnt] = Edge(y, hed[x], w), hed[x] = cnt;
e[++cnt] = Edge(x, hed[y], 0), hed[y] = cnt;
}
inline bool BFS() {
queue <int> q;
for (int i = S; i <= T; ++i) {
dis[i] = 0;
}
for (q.push(S), dis[S] = 1; !q.empty(); q.pop()) {
int x = q.front();
for (int i = hed[x]; i; i = e[i].v) {
if (e[i].w && !dis[e[i].p]) {
dis[e[i].p] = dis[x] + 1, q.push(e[i].p);
}
}
}
return dis[T];
}
inline int DFS(int x, int f) {
if (x == T) {
return f;
}
int r = 0, w;
for (int &i = cur[x]; i; i = e[i].v) {
if (e[i].w && dis[e[i].p] == dis[x] + 1) {
w = DFS(e[i].p, min(f - r, e[i].w));
e[i].w -= w, e[i ^ 1].w += w, r += w;
if (r == f) {
return r;
}
}
}
dis[x] = -1;
return r;
}
inline int Dinic() {
int r = 0;
while (BFS()) {
for (int i = S; i <= T; ++i) {
cur[i] = hed[i];
}
r += DFS(S, inf);
}
return r;
}
inline bool Check(int l, int r, int mid) {
T = r - l + m + 1, cnt = 1;
for (int i = S; i <= T; ++i) {
hed[i] = 0;
}
for (int i = 0; i < r - l; ++i) {
AddEdge(S, i + 1, 1);
}
for (int i = 0; i < m; ++i) {
AddEdge(i + r - l + 1, T, 1);
}
for (int i = l; i < r; ++i) {
for (int j = 0; j < m; ++j) {
if (run[i][j] <= mid) {
AddEdge(i - l + 1, j + r - l + 1, 1), edg[i][j] = cnt;
}
}
}
if (Dinic() != r - l) {
return false;
}
for (int i = l; i < r; ++i) {
for (int j = 0; j < m; ++j) {
if (run[i][j] <= mid && e[edg[i][j]].w) {
per[i] = j;
}
}
}
return true;
}
inline void Solve(int l, int r) {
int L = 1, R = 10000, ret = R;
while (L <= R) {
int mid = L + R >> 1;
if (Check(l, r, mid)) {
ret = mid, R = mid - 1;
} else {
L = mid + 1;
}
}
ans += ret + 1;
}
int main() {
freopen("placement8.in", "r", stdin);
freopen("placement8.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n), ans = -1;
Solve(0, 1);
for (int i = 1, j = i + 50; i < n - 1; Solve(i, j), i += 50, j += 50);
Solve(n - 1, n);
bes = per;
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
爬山。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int inf = 0x3f3f3f3f;
struct Event {
int o, v, t;
Event(int o = 0, int v = 0, int t = 0):o(o), v(v), t(t) {}
bool operator < (const Event &b) const {
return t > b.t;
}
};
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
inline int Calc() {
vector int , vector <int>, greater <int>>> que(m);
priority_queue q;
vector <bool> cur(m);
vector <int> deg(n);
int ret = 0;
for (int i = 0; i < n; ++i) {
for (auto j : adj[i]) {
++deg[j];
}
}
for (int i = 0; i < n; ++i) {
if (!deg[i]) {
if (!cur[per[i]]) {
cur[per[i]] = true, q.push(Event(1, i, run[i][per[i]] + ret));
} else {
que[per[i]].push(i);
}
}
}
while (!q.empty()) {
Event e = q.top();
q.pop();
int x = e.v;
ret = e.t;
if (e.o) {
for (auto y : adj[x]) {
q.push(Event(0, y, ret + mov[per[x]][per[y]]));
}
cur[per[x]] = false;
if (!que[per[x]].empty()) {
int i = que[per[x]].top();
que[per[x]].pop();
cur[per[x]] = true, q.push(Event(1, i, run[i][per[i]] + ret));
}
} else {
if (!--deg[x]) {
if (!cur[per[x]]) {
cur[per[x]] = true, q.push(Event(1, x, run[x][per[x]] + ret));
} else {
que[per[x]].push(x);
}
}
}
}
return ret;
}
int main() {
freopen("placement9.in", "r", stdin);
freopen("placement9.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n), ans = inf, srand(time(0));
for (int t = 0; t < 20; ++t) {
for (int i = 0; i < n; ++i) {
per[i] = rand() % m;
}
for (int i = 0; i < 2000; ++i) {
int x = rand() % n, lst = inf, val = -1;
for (int j = 0; j < m; ++j) {
per[x] = j;
int cur = Calc();
if (CheckMin(lst, cur)) {
val = j;
}
}
per[x] = val;
if (CheckMin(ans, lst)) {
bes = per;
Debug("ans = %d\n", ans);
for (int j = 0; j < n; ++j) {
Debug("%d%c", bes[j] + 1, j == n - 1 ? '\n' : ' ');
}
}
}
Debug("t = %d\n", t);
}
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}
爬山。
#include
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int inf = 0x3f3f3f3f;
vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;
inline int Calc() {
int ret = 0;
for (int i = 0; i < n; ++i) {
ret += run[i][per[i]];
}
for (int i = 0; i < n; ++i) {
for (auto j : adj[i]) {
ret += mov[per[i]][per[j]];
}
}
return ret;
}
int main() {
freopen("placement10.in", "r", stdin);
freopen("placement10.out", "w", stdout);
Read(n), Read(q), Read(m), Read(o);
adj.resize(n), run.resize(n), mov.resize(m);
for (int i = 0, x, y; i < q; ++i) {
Read(x), Read(y), --x, --y;
adj[x].pb(y);
}
for (int i = 0; i < n; ++i) {
run[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(run[i][j]);
}
}
for (int i = 0; i < m; ++i) {
mov[i].resize(m);
for (int j = 0; j < m; ++j) {
Read(mov[i][j]);
}
}
per.resize(n), ans = inf, srand(time(0));
for (int t = 0; t < 10; ++t) {
for (int i = 0; i < n; ++i) {
per[i] = rand() % m;
}
int lst = Calc();
for (int i = 0; i < 100000; ++i) {
int x = rand() % n, y = rand() % m, z = per[x];
per[x] = y;
int cur = Calc();
if (!CheckMin(lst, cur)) {
per[x] = z;
} else {
if (CheckMin(ans, cur)) {
bes = per;
}
}
}
}
Debug("%d\n", ans);
for (int i = 0; i < n; ++i) {
printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
}
return 0;
}