QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#697656 | #7069. Farm | SunsetGlow95 | RE | 0ms | 0kb | C++14 | 4.8kb | 2024-11-01 15:15:29 | 2024-11-01 15:15:39 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
const int MXN = 100005;
const int MXM = 500005;
const int MXQ = 20;
const int MXP = MXQ * 8;
const int MXE = MXP + MXQ * 2;
const int INF = 1000000000;
const int MXLG = 18;
int N, M, Q, con[MXQ][2], fa[MXN];
tuple<int, int, int, int> oes[MXM], ves[MXE];
bool emark[MXM], vmark[MXN], chosen[MXM];
vector<pair<int, int>> te[MXN];
int dfn[MXN], col[MXN], jump[MXN][MXLG], mxe[MXN][MXLG], dep[MXN];
int stk[MXP], top(-1), pid[MXP], rpid[MXN], P, E;
int ecnt, esum, ans(INF);
int read() {
int x(0), c(getchar());
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + (c - '0'), c = getchar();
return x;
}
int find(int x) { return x ^ fa[x] ? fa[x] = find(fa[x]) : x; }
void prework(int p, int f, int w, int c) {
static int did = 0;
col[p] = c, dfn[p] = did++;
jump[p][0] = f, mxe[p][0] = w;
for (int i(1); ~jump[p][i - 1]; ++i) {
jump[p][i] = jump[jump[p][i - 1]][i - 1];
mxe[p][i] = max(mxe[p][i - 1], mxe[jump[p][i - 1]][i - 1]);
}
for (auto e : te[p]) {
if (e.first == f) continue;
dep[e.first] = dep[p] + 1;
prework(e.first, p, e.second, c);
}
}
int getlca(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
for (int i(MXLG - 1); ~i; --i)
if (((dep[x] - dep[y]) >> i) & 1) x = jump[x][i];
if (x == y) return x;
for (int i(MXLG - 1); ~i; --i)
if (jump[x][i] != jump[y][i]) x = jump[x][i], y = jump[y][i];
return jump[x][0];
}
void addedge(int x, int y) {
// y is an ancestor of x
int v(-1);
for (int p(x), i(MXLG - 1); ~i; --i)
if (((dep[x] - dep[y]) >> i) & 1)
v = max(v, mxe[p][i]), p = jump[p][i];
--ecnt, esum -= v;
ves[E++] = make_tuple(v, rpid[x], rpid[y], -1);
//cout << "tree1" << endl;
}
int main() {
freopen("bridge.in", "r", stdin);
freopen("bridge.out", "w", stdout);
// input
N = read(), M = read();
for (int i(0), u(0), v(0), w(0); i != M; ++i)
u = read() - 1, v = read() - 1, w = read(),
oes[i] = make_tuple(w, u, v, i);
Q = read();
for (int i(0); i != Q; ++i)
emark[con[i][0] = read() - 1] = emark[con[i][1] = read() - 1] = true;
// get the min spanning forest of unmarked edges
sort(oes, oes + M);
for (int i(0); i != N; ++i) fa[i] = i;
for (int i(0); i != M; ++i) {
auto e(oes[i]);
int x(get<1>(e)), y(get<2>(e)), w(get<0>(e));
if (emark[get<3>(e)]) {
vmark[x] = vmark[y] = true;
continue;
}
if (find(x) == find(y)) continue;
fa[find(x)] = find(y);
++ecnt, esum += w;
te[x].emplace_back(y, w);
te[y].emplace_back(x, w);
}
// get the virtual forest of marked vertices, and construct the edge set
memset(dfn, -1, sizeof dfn);
memset(jump, -1, sizeof jump);
memset(rpid, -1, sizeof rpid);
for (int i(0); i != N; ++i) {
if (dfn[i] == -1) prework(i, -1, INF, i);
if (vmark[i]) rpid[i] = P, pid[P++] = i;
}
sort(pid, pid + P, [](int x, int y) -> bool { return dfn[x] < dfn[y]; });
for (int i(0), op(P); i != op; ++i) {
int p(pid[i]);
if (~top && col[stk[top]] != col[p]) {
for (int lst(stk[top--]); ~top; lst = stk[top--])
addedge(lst, stk[top]);
}
if (top == -1) {
stk[++top] = p;
continue;
}
int f(getlca(stk[top], p)), lst(-1);
while (dep[stk[top]] > dep[f]) {
if (~lst) addedge(lst, stk[top]);
lst = stk[top--];
}
if (top == -1 || stk[top] != f) rpid[f] = P, pid[P++] = f, stk[++top] = f;
if (~lst) addedge(lst, stk[top]);
stk[++top] = p;
}
if (~top)
for (int lst(stk[top--]); ~top; lst = stk[top--])
addedge(lst, stk[top]);
sort(pid, pid + P,
[](int x, int y) -> bool { return rpid[x] < rpid[y]; });
for (int i(0); i != M; ++i) {
if (!emark[get<3>(oes[i])]) continue;
auto e(oes[i]);
ves[E++] = make_tuple(get<0>(e), rpid[get<1>(e)], rpid[get<2>(e)], get<3>(e));
}
sort(ves, ves + E);
// try the choices one by one
for (int i(0); i != (1 << Q); ++i) {
for (int j(0); j != P; ++j) fa[j] = j;
for (int j(0); j != Q; ++j)
chosen[con[j][(i >> j) & 1]] = true;
int tcnt(ecnt), tsum(esum);
for (int j(0); j != E; ++j) {
if (get<3>(ves[j]) == -1 || !chosen[get<3>(ves[j])]) continue;
tsum += get<0>(ves[j]);
int x(find(get<1>(ves[j]))), y(find(get<2>(ves[j])));
if (x != y) fa[x] = y, ++tcnt;
}
for (int j(0); j != E; ++j) {
int x(find(get<1>(ves[j]))), y(find(get<2>(ves[j])));
if (x == y) continue;
tsum += get<0>(ves[j]);
fa[x] = y, ++tcnt;
}
if (tcnt == N - 1) ans = min(ans, tsum);
for (int j(0); j != Q; ++j)
chosen[con[j][(i >> j) & 1]] = false;
}
if (ans == INF) puts("mumuyibarenkoumumumu");
else printf("%d\n", ans);
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Dangerous Syscalls
input:
4 6 1 1 2 2 4 3 1 1 4 2 4 4 3 2 4 1 3 4 1 1 2