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; } ```\]

posted @ 2024-04-22 14:37  cxqghzj  阅读(7)  评论(0编辑  收藏  举报