P6700 / YC272B [ 20240413 CQYC省选模拟赛 T2 ] 编辑(edit)
f_{i - 1, S} + dis_{i, j} \
f_{i, T} = f_{i, S} + dis_{i, j}
\[
其中,$T$ 为破开 $i$ 和 $j$ 的集合。
显然,基环是需要考虑的,可以将基环上的边看作破开当前基环的贡献。
特判掉全为自环即可。
## Code
``` cpp
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <stack>
#include <vector>
#include <bitset>
#include <assert.h>
#define int long long
using namespace std;
#ifdef ONLINE_JUDGE
/* #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++) */
/* char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf; */
#endif
int read() {
int p = 0, flg = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') flg = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
p = p * 10 + c - '0';
c = getchar();
}
return p * flg;
}
void write(int x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x > 9) {
write(x / 10);
}
putchar(x % 10 + '0');
}
bool _stmer;
const int N = 1e6 + 5, M = 27, inf = 2e9;
char strbuf[N];
namespace G {
array <int, M> fir;
array <int, M * M> nex, to;
int cnt = 1;
void add(int x, int y) {
cnt++;
nex[cnt] = fir[x];
to[cnt] = y;
fir[x] = cnt;
}
} //namespace G
array <array <int, M>, M> isl;
bitset <M> lab;
array <int, M> dfn;
int cnt;
bitset <M> vis;
stack <int> stk;
array <vector <int>, M> col;
void dfs(int x) {
if (!lab[x]) return;
cnt++, dfn[x] = cnt;
stk.push(x), vis[x] = 1;
for (int i = G::fir[x]; i; i = G::nex[i]) {
if (!dfn[G::to[i]])
dfs(G::to[i]);
else if (dfn[G::to[i]] <= dfn[x])
while (!stk.empty() && dfn[stk.top()] >= dfn[G::to[i]])
col[x].push_back(stk.top()), vis[stk.top()] = 0, stk.pop();
}
if (vis[x]) vis[x] = 0, stk.pop();
}
array <array <int, 1 << 13>, M> f;
array <int, M> idx, psl;
bool _edmer;
signed main() {
/* freopen("1.in", "r", stdin); */
cerr << (&_stmer - &_edmer) / 1024.0 / 1024.0 << "MB\n";
int n = read(), w = read();
string s, t;
scanf("%s", strbuf), s = strbuf, s = " " + s;
scanf("%s", strbuf), t = strbuf, t = " " + t;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= 26; j++)
isl[s[i] - 'a' + 1][j] += (j != t[i] - 'a' + 1);
for (auto k : s) lab[k - 'a' + 1] = 1;
for (int i = 1; i <= 26; i++)
for (int j = 1; j <= 26; j++)
if (i != j) isl[i][j] += w;
for (int i = 1; i <= 26; i++) {
int v = min_element(isl[i].begin() + 1, isl[i].begin() + 27)
- isl[i].begin();
G::add(v, i), psl[i] = v;
}
for (int i = 1; i <= 26; i++)
if (!dfn[i]) dfs(i);
int res = 0;
for (int i = 1; i <= 26; i++) res += col[i].size();
bool flg = 0;
int len = 0;
f[0].fill(inf);
for (int i = 1; i <= 26; i++) {
f[i].fill(inf);
if (col[i].size() <= 1) continue;
len++, flg = 1;
for (auto k : col[i])
idx[k] = len;
}
/* for (int i = 1; i <= 26; i++) */
/* for (int j = 1; j <= 26; j++) */
/* write(isl[i][j]), putchar(" \n"[j == 26]); */
f[0][0] = 0;
for (int i = 1; i <= 26; i++) {
for (int S = (1 << len) - 1; ~S; S--) {
for (int j = 1; j <= 26; j++) {
if (idx[i] && j == psl[i]) {
f[i][S] = min(f[i - 1][S] + isl[i][j], f[i][S]);
/* if (S == 31 && f[i][S] == 0) */
/* write(i), puts("@"); */
}
if (j != psl[i] || !idx[i]) {
int T = S;
if (idx[i]) T |= 1 << (idx[i] - 1);
if (idx[j]) T |= 1 << (idx[j] - 1);
f[i][T] = min(f[i - 1][S] + isl[i][j], f[i][T]);
/* if (T == 31 && !f[i][T] && f[i][T] == f[i - 1][S] + isl[i][j]) */
/* write(isl[i][j]), puts("@"); */
}
}
}
}
int ans = inf;
for (int S = (res == 26 && flg); S < 1 << len; S++)
ans = min(f[26][S] + (len - (int)bitset <26>(S).count()) * w, ans);
/* assert(ans); */
write(ans), puts("");
return 0;
}
```\]