贴一下使用dsu和lca的代码,dsu的代码很简单,可以马上写出来,但是lca的代码就不熟练了。这里lca的计算还是用了dfs的访问时间标记,我想起来割边, 割点的判断, dfu[u], low[u],的的使用,还有lca的离线算法,tarjan算法,然后又查到了求强连通分量的算法,也是使用访问时间标记,这些算法,有时间好好整理一下。dfs判断回路。等等。想起来再补充。
#include<bits/stdc++.h>
#define pb push_back
#define FOR(i, n) for (int i = 0; i < (int)n; ++i)
#define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
typedef long long ll;
using namespace std;
typedef pair<int, int> pii;
const int maxn = 2e5 + ;
const int inf = 1e9 + ;
int n, m;
int w[maxn], c[maxn], a[maxn], b[maxn];
// dsu disjoint set union //find and union
int sz[maxn], p[maxn];
void init() {
for (int i = ; i <= n; i++) {
sz[i] = ; p[i] = i;
}
}
int get(int x) {
if(x == p[x]) return x;
return p[x] = get(p[x]);
}
bool unite(int x, int y) {
x = get(x); y = get(y);
if(x == y) return ;
if(sz[x] > sz[y]) swap(x, y);
sz[y] += sz[x];
p[x] = y;
return ;
} struct node {
int to, idx, w;
node(int to, int idx, int w) : to(to), idx(idx), w(w) {}
}; vector<node> g[maxn];
int depth[maxn];
bool used[maxn];
pii fmaxi[maxn][];
int tin[maxn], tout[maxn], timer;
int fup[maxn][];
void dfs(int v, int p, int wup, int eidx, int dep) {
tin[v] = ++timer;
fup[v][] = p;
fmaxi[v][] = {wup, eidx};
depth[v] = dep;
for (int i = ; i < ; i++) {
fup[v][i] = fup[fup[v][i - ] ][i - ];
fmaxi[v][i] = max(fmaxi[v][i - ], fmaxi[fup[v][i - ] ][i - ]);
}
for (auto it : g[v]) {
int to = it.to;
int idx = it.idx;
int w = it.w;
if(to == p) continue;
dfs(to, v, w, idx, dep + );
}
tout[v] = ++timer;
} bool isAncestor(int x, int y) {
return tin[x] <= tin[y] && tout[x] >= tout[y];
}
int lca(int x, int y) {
if(isAncestor(x, y)) return x;
if(isAncestor(y, x)) return y;
for (int i = - ; i >= ; i--) {
if(!isAncestor(fup[x][i], y)) x = fup[x][i];
}
return fup[x][];
}
pii getfmax1(int x, int p) {
int len = depth[x] - depth[p];
pii res = {-inf, -inf};
for (int i = - ; i >= ; i--) {
if((len >> i) & ) {
len ^= ( << i);
res = max(res, fmaxi[x][i]);
x = fup[x][i];
}
}
return res;
}
pii getfmax(int x, int y) {
int z = lca(x, y);
return max(getfmax1(x, z), getfmax1(y, z));
}
int S;
ll sum;
int perm[maxn];
void solve() {
cin >> n >> m;
init();
for (int i = ; i <= m; i++) cin >> w[i];
for (int i = ; i <= m; i++) cin >> c[i];
for (int i = ; i <= m; i++) cin >> a[i] >> b[i];
cin >> S;
for (int i = ; i <= m; i++)
perm[i] = i;
sort(perm + , perm + m + , [](int i, int j) {return w[i] < w[j];});
vector<int> e;
for (int j = ; j <= m; j++) {
int i = perm[j];
if(unite(a[i], b[i])) {
e.pb(i);
sum += w[i];
}
}
//cout << sum << endl;
assert((int)e.size() == n - );
for (int idx : e) {
g[a[idx] ].pb({b[idx], idx, w[idx] });
g[b[idx] ].pb({a[idx], idx, w[idx] });
}
dfs(, , -inf, -inf, );
pair<ll, pii> best = {(ll)1e18, {-, -}};
for (int idx = ; idx <= m; idx++) {
pii z = getfmax(a[idx], b[idx]);
ll nsum = sum - z.first + w[idx] - (S / c[idx]);
pair<ll, pii> cur = {nsum, {z.second, idx} };
best = min(best, cur);
}
assert(best.second.first != -);
cout << best.first << endl;
for (int idx : e) {
used[idx] = ;
}
used[best.second.first] = ;
used[best.second.second] = ;
for (int i = ; i <= m; i++) {
if(used[i]) {
cout << i << " ";
int ww = w[i];
if(i == best.second.second)
ww -= S / c[i];
cout << ww << endl;
}
} } int main() {
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
solve();
return ;
} void dfs2(int x, int lt) {
fup[x][] = lt;
for (auto it : g[x]) {
int to = it.to;
int idx = it.idx;
if(to == lt) continue;
fmaxi[to][] = {w[idx], idx};
depth[to] = depth[x] + ;
dfs2(to, x);
}
}
void build(int root) {
dfs2(, );
for (int i = ; i <= ; i++) {
for (int x = ; x <= n; x++) {
fup[x][i] = fup[fup[x][i - ] ][i - ];
fmaxi[x][i] = max(fmaxi[fup[x][i - ] ][i - ], fmaxi[x][i - ] ); }
}
}
int adv(int x, int v, pii & ret) {
for (int i = ; ( << i) <= v; i++) {
if((v >> i) & ) {
ret = max(ret, fmaxi[x][i]);
x = fup[x][i];
}
}
return x;
}
pii lca2(int x, int y) {
pii ret = {-, -};
if(depth[x] > depth[y]) x = adv(x, depth[x] - depth[y], ret);
else y = adv(y, depth[y] - depth[x], ret);
if(x == y) return ret;
for (int i = ; i >= ; i--) {
if(fup[x][i] != fup[y][i]) {
ret = max(ret, fmaxi[x][i]);
ret = max(ret, fmaxi[y][i]);
x = fup[x][i];
y = fup[y][i];
}
}
ret = max(ret, fmaxi[x][]);
ret = max(ret, fmaxi[y][]);
return ret;
}