贴一下使用dsu和lca的代码,dsu的代码很简单,可以马上写出来,但是lca的代码就不熟练了。这里lca的计算还是用了dfs的访问时间标记,我想起来割边, 割点的判断, dfu[u], low[u],的的使用,还有lca的离线算法,tarjan算法,然后又查到了求强连通分量的算法,也是使用访问时间标记,这些算法,有时间好好整理一下。dfs判断回路。等等。想起来再补充。
1 #include<bits/stdc++.h> 2 #define pb push_back 3 #define FOR(i, n) for (int i = 0; i < (int)n; ++i) 4 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 5 typedef long long ll; 6 using namespace std; 7 typedef pair<int, int> pii; 8 const int maxn = 2e5 + 10; 9 const int inf = 1e9 + 7; 10 int n, m; 11 int w[maxn], c[maxn], a[maxn], b[maxn]; 12 // dsu disjoint set union //find and union 13 int sz[maxn], p[maxn]; 14 void init() { 15 for (int i = 1; i <= n; i++) { 16 sz[i] = 1; p[i] = i; 17 } 18 } 19 int get(int x) { 20 if(x == p[x]) return x; 21 return p[x] = get(p[x]); 22 } 23 bool unite(int x, int y) { 24 x = get(x); y = get(y); 25 if(x == y) return 0; 26 if(sz[x] > sz[y]) swap(x, y); 27 sz[y] += sz[x]; 28 p[x] = y; 29 return 1; 30 } 31 32 struct node { 33 int to, idx, w; 34 node(int to, int idx, int w) : to(to), idx(idx), w(w) {} 35 }; 36 37 vector<node> g[maxn]; 38 int depth[maxn]; 39 bool used[maxn]; 40 pii fmaxi[maxn][20]; 41 int tin[maxn], tout[maxn], timer; 42 int fup[maxn][20]; 43 void dfs(int v, int p, int wup, int eidx, int dep) { 44 tin[v] = ++timer; 45 fup[v][0] = p; 46 fmaxi[v][0] = {wup, eidx}; 47 depth[v] = dep; 48 for (int i = 1; i < 20; i++) { 49 fup[v][i] = fup[fup[v][i - 1] ][i - 1]; 50 fmaxi[v][i] = max(fmaxi[v][i - 1], fmaxi[fup[v][i - 1] ][i - 1]); 51 } 52 for (auto it : g[v]) { 53 int to = it.to; 54 int idx = it.idx; 55 int w = it.w; 56 if(to == p) continue; 57 dfs(to, v, w, idx, dep + 1); 58 } 59 tout[v] = ++timer; 60 } 61 62 bool isAncestor(int x, int y) { 63 return tin[x] <= tin[y] && tout[x] >= tout[y]; 64 } 65 int lca(int x, int y) { 66 if(isAncestor(x, y)) return x; 67 if(isAncestor(y, x)) return y; 68 for (int i = 20 - 1; i >= 0; i--) { 69 if(!isAncestor(fup[x][i], y)) x = fup[x][i]; 70 } 71 return fup[x][0]; 72 } 73 pii getfmax1(int x, int p) { 74 int len = depth[x] - depth[p]; 75 pii res = {-inf, -inf}; 76 for (int i = 20 - 1; i >= 0; i--) { 77 if((len >> i) & 1) { 78 len ^= (1 << i); 79 res = max(res, fmaxi[x][i]); 80 x = fup[x][i]; 81 } 82 } 83 return res; 84 } 85 pii getfmax(int x, int y) { 86 int z = lca(x, y); 87 return max(getfmax1(x, z), getfmax1(y, z)); 88 } 89 int S; 90 ll sum; 91 int perm[maxn]; 92 void solve() { 93 cin >> n >> m; 94 init(); 95 for (int i = 1; i <= m; i++) cin >> w[i]; 96 for (int i = 1; i <= m; i++) cin >> c[i]; 97 for (int i = 1; i <= m; i++) cin >> a[i] >> b[i]; 98 cin >> S; 99 for (int i = 1; i <= m; i++) 100 perm[i] = i; 101 sort(perm + 1, perm + m + 1, [](int i, int j) {return w[i] < w[j];}); 102 vector<int> e; 103 for (int j = 1; j <= m; j++) { 104 int i = perm[j]; 105 if(unite(a[i], b[i])) { 106 e.pb(i); 107 sum += w[i]; 108 } 109 } 110 //cout << sum << endl; 111 assert((int)e.size() == n - 1); 112 for (int idx : e) { 113 g[a[idx] ].pb({b[idx], idx, w[idx] }); 114 g[b[idx] ].pb({a[idx], idx, w[idx] }); 115 } 116 dfs(1, 1, -inf, -inf, 0); 117 pair<ll, pii> best = {(ll)1e18, {-1, -1}}; 118 for (int idx = 1; idx <= m; idx++) { 119 pii z = getfmax(a[idx], b[idx]); 120 ll nsum = sum - z.first + w[idx] - (S / c[idx]); 121 pair<ll, pii> cur = {nsum, {z.second, idx} }; 122 best = min(best, cur); 123 } 124 assert(best.second.first != -1); 125 cout << best.first << endl; 126 for (int idx : e) { 127 used[idx] = 1; 128 } 129 used[best.second.first] = 0; 130 used[best.second.second] = 1; 131 for (int i = 1; i <= m; i++) { 132 if(used[i]) { 133 cout << i << " "; 134 int ww = w[i]; 135 if(i == best.second.second) 136 ww -= S / c[i]; 137 cout << ww << endl; 138 } 139 } 140 141 } 142 143 int main() { 144 //freopen("test.in", "r", stdin); 145 //freopen("test.out", "w", stdout); 146 solve(); 147 return 0; 148 } 149 150 void dfs2(int x, int lt) { 151 fup[x][0] = lt; 152 for (auto it : g[x]) { 153 int to = it.to; 154 int idx = it.idx; 155 if(to == lt) continue; 156 fmaxi[to][0] = {w[idx], idx}; 157 depth[to] = depth[x] + 1; 158 dfs2(to, x); 159 } 160 } 161 void build(int root) { 162 dfs2(1, 1); 163 for (int i = 1; i <= 18; i++) { 164 for (int x = 1; x <= n; x++) { 165 fup[x][i] = fup[fup[x][i - 1] ][i - 1]; 166 fmaxi[x][i] = max(fmaxi[fup[x][i - 1] ][i - 1], fmaxi[x][i - 1] ); 167 168 } 169 } 170 } 171 int adv(int x, int v, pii & ret) { 172 for (int i = 0; (1 << i) <= v; i++) { 173 if((v >> i) & 1) { 174 ret = max(ret, fmaxi[x][i]); 175 x = fup[x][i]; 176 } 177 } 178 return x; 179 } 180 pii lca2(int x, int y) { 181 pii ret = {-1, -1}; 182 if(depth[x] > depth[y]) x = adv(x, depth[x] - depth[y], ret); 183 else y = adv(y, depth[y] - depth[x], ret); 184 if(x == y) return ret; 185 for (int i = 17; i >= 0; i--) { 186 if(fup[x][i] != fup[y][i]) { 187 ret = max(ret, fmaxi[x][i]); 188 ret = max(ret, fmaxi[y][i]); 189 x = fup[x][i]; 190 y = fup[y][i]; 191 } 192 } 193 ret = max(ret, fmaxi[x][0]); 194 ret = max(ret, fmaxi[y][0]); 195 return ret; 196 }