其实是求树上的路径间的数据第K大的题目。
果断主席树 + LCA。
初始流量是这条路径上的最小值。
若a<=b,显然直接为s->t建立pipe可以使流量最优;
否则,对【0, 10**4】二分得到boundry,使得boundry * n_edge - sum_edge <= k/b, 或者建立s->t,然后不断extend s->t。
1 /* 4729 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <algorithm> 12 #include <cstdio> 13 #include <cmath> 14 #include <ctime> 15 #include <cstring> 16 #include <climits> 17 #include <cctype> 18 #include <cassert> 19 #include <functional> 20 #include <iterator> 21 #include <iomanip> 22 using namespace std; 23 //#pragma comment(linker,"/STACK:102400000,1024000") 24 25 #define sti set<int> 26 #define stpii set<pair<int, int> > 27 #define mpii map<int,int> 28 #define vi vector<int> 29 #define pii pair<int,int> 30 #define vpii vector<pair<int,int> > 31 #define rep(i, a, n) for (int i=a;i<n;++i) 32 #define per(i, a, n) for (int i=n-1;i>=a;--i) 33 #define clr clear 34 #define pb push_back 35 #define mp make_pair 36 #define fir first 37 #define sec second 38 #define all(x) (x).begin(),(x).end() 39 #define SZ(x) ((int)(x).size()) 40 // #define lson l, mid, rt<<1 41 // #define rson mid+1, r, rt<<1|1 42 43 typedef struct { 44 int v, c, nxt; 45 } edge_t; 46 47 const int maxn = 1e5+5; 48 const int m = 10005; 49 const int maxm = maxn * 20; 50 int T[maxn]; 51 int lson[maxm], rson[maxm], c[maxm], sum[maxm]; 52 int head[maxn], l; 53 edge_t E[maxn<<1]; 54 int tot, n, q; 55 int beg[maxn]; 56 int V[maxn<<1], D[maxn<<1], top; 57 int dp[18][maxn<<1]; 58 59 void init() { 60 memset(head, -1, sizeof(head)); 61 l = top = 0; 62 tot = 1; 63 } 64 65 int Build(int l, int r) { 66 int rt = tot++; 67 68 c[rt] = sum[rt] = 0; 69 if (l == r) 70 return rt; 71 72 int mid = (l + r) >> 1; 73 74 lson[rt] = Build(l, mid); 75 rson[rt] = Build(mid+1, r); 76 77 return rt; 78 } 79 80 int Insert(int rt, int x, int val) { 81 int nrt = tot++, ret = nrt; 82 int l = 0, r = m - 1, mid; 83 84 c[nrt] = c[rt] + 1; 85 sum[nrt] = sum[rt] + val; 86 while (l < r) { 87 mid = (l + r) >> 1; 88 if (x <= mid) { 89 lson[nrt] = tot++; 90 rson[nrt] = rson[rt]; 91 nrt = lson[nrt]; 92 rt = lson[rt]; 93 r = mid; 94 } else { 95 lson[nrt] = lson[rt]; 96 rson[nrt] = tot++; 97 nrt = rson[nrt]; 98 rt = rson[rt]; 99 l = mid + 1; 100 } 101 c[nrt] = c[rt] + 1; 102 sum[nrt] = sum[rt] + val; 103 } 104 105 return ret; 106 } 107 108 int Query_kth(int urt, int vrt, int frt, int k) { 109 int l = 0, r = m - 1, mid; 110 int tmp; 111 112 while (l < r) { 113 mid = (l + r) >> 1; 114 tmp = c[lson[urt]] + c[lson[vrt]] - (c[lson[frt]] << 1); 115 if (tmp >= k) { 116 urt = lson[urt]; 117 vrt = lson[vrt]; 118 frt = lson[frt]; 119 r = mid; 120 } else { 121 k -= tmp; 122 urt = rson[urt]; 123 vrt = rson[vrt]; 124 frt = rson[frt]; 125 l = mid + 1; 126 } 127 } 128 129 return l; 130 } 131 132 int Query_Bound(int urt, int vrt, int frt, int delta) { 133 int l = 0, r = m - 1, mid; 134 int cc = 0, csum = 0; 135 int tc, tsum; 136 int ans = 0, tmp; 137 138 while (l < r) { 139 mid = (l + r) >> 1; 140 tc = c[lson[urt]] + c[lson[vrt]] - (c[lson[frt]] << 1); 141 tsum = sum[lson[urt]] + sum[lson[vrt]] - (sum[lson[frt]] << 1); 142 tmp = mid*(tc+cc)-(tsum+csum); 143 if (tmp <= delta) 144 ans = max(ans, mid); 145 if (mid*(tc+cc)-(tsum+csum) >= delta) { 146 urt = lson[urt]; 147 vrt = lson[vrt]; 148 frt = lson[frt]; 149 r = mid; 150 } else { 151 urt = rson[urt]; 152 vrt = rson[vrt]; 153 frt = rson[frt]; 154 cc += tc; 155 csum += tsum; 156 l = mid + 1; 157 } 158 } 159 160 return ans; 161 } 162 163 void addEdge(int u, int v, int c) { 164 E[l].v = v; 165 E[l].c = c; 166 E[l].nxt = head[u]; 167 head[u] = l++; 168 169 E[l].v = u; 170 E[l].c = c; 171 E[l].nxt = head[v]; 172 head[v] = l++; 173 } 174 175 void dfs(int u, int fa, int dep) { 176 int v, k; 177 178 V[++top] = u; 179 D[top] = dep; 180 beg[u] = top; 181 182 for (k=head[u]; k!=-1; k=E[k].nxt) { 183 v = E[k].v; 184 if (v == fa) 185 continue; 186 T[v] = Insert(T[u], E[k].c, E[k].c); 187 dfs(v, u, dep+1); 188 V[++top] = u; 189 D[top] = dep; 190 } 191 } 192 193 void Init_RMQ(int n) { 194 int i, j; 195 196 for (i=1; i<=n; ++i) 197 dp[0][i] = i; 198 for (j=1; (1<<j)<=n; ++j) 199 for (i=1; i+(1<<j)-1<=n; ++i) 200 if (D[dp[j-1][i]] < D[dp[j-1][i+(1<<(j-1))]]) 201 dp[j][i] = dp[j-1][i]; 202 else 203 dp[j][i] = dp[j-1][i+(1<<(j-1))]; 204 } 205 206 int RMQ(int l, int r) { 207 if (l > r) 208 swap(l, r); 209 210 int k = 0; 211 212 while (1<<(k+1) <= r-l+1) 213 ++k; 214 215 if (D[dp[k][l]] < D[dp[k][r-(1<<k)+1]]) 216 return V[dp[k][l]]; 217 else 218 return V[dp[k][r-(1<<k)+1]]; 219 } 220 221 void solve() { 222 T[1] = Build(0, m - 1); 223 dfs(1, 0, 0); 224 Init_RMQ(top); 225 226 int u, v, k, a, b; 227 int lca; 228 int ans, tmp, org; 229 230 while (q--) { 231 scanf("%d %d %d %d %d", &u, &v, &k, &a, &b); 232 lca = RMQ(beg[u], beg[v]); 233 org = Query_kth(T[u], T[v], T[lca], 1); 234 #ifndef ONLINE_JUDGE 235 // printf("f = %d\n", lca); 236 #endif 237 if (a <= b) { 238 ans = org + k / a; 239 } else { 240 ans = org; 241 if (k >= a) 242 ans += 1 + (k-a)/b; 243 tmp = Query_Bound(T[u], T[v], T[lca], k/b); 244 #ifndef ONLINE_JUDGE 245 // printf("org = %d, ans = %d, bound = %d\n", org, ans, tmp); 246 #endif 247 ans = max(ans, tmp); 248 } 249 printf("%d\n", ans); 250 } 251 } 252 253 int main() { 254 ios::sync_with_stdio(false); 255 #ifndef ONLINE_JUDGE 256 freopen("data.in", "r", stdin); 257 freopen("data.out", "w", stdout); 258 #endif 259 260 int t; 261 int u, v, c; 262 263 scanf("%d", &t); 264 rep(tt, 1, t+1) { 265 init(); 266 scanf("%d %d", &n, &q); 267 rep(i, 1, n) { 268 scanf("%d %d %d", &u, &v, &c); 269 addEdge(u, v, c); 270 } 271 printf("Case #%d:\n", tt); 272 solve(); 273 } 274 275 #ifndef ONLINE_JUDGE 276 printf("time = %d.\n", (int)clock()); 277 #endif 278 279 return 0; 280 }
数据发生器。
1 from copy import deepcopy 2 from random import randint, shuffle 3 import shutil 4 import string 5 6 7 def GenDataIn(): 8 with open("data.in", "w") as fout: 9 t = 10 10 bound = 10**4 11 fout.write("%d\n" % (t)) 12 for tt in xrange(t): 13 n = randint(100, 200) 14 q = randint(100, 200) 15 fout.write("%d %d\n" % (n, q)) 16 ust = [1] 17 vst = range(2, n+1) 18 for i in xrange(1, n): 19 idx = randint(0, len(ust)-1) 20 u = ust[idx] 21 idx = randint(0, len(vst)-1) 22 v = vst[idx] 23 ust.append(v) 24 vst.remove(v) 25 c = randint(0, bound-1) 26 fout.write("%d %d %d\n" % (u, v, c)) 27 for i in xrange(q): 28 u = randint(1, n) 29 while True: 30 v = randint(1, n) 31 if v!=u: 32 break 33 k = randint(0, bound) 34 a = randint(1, bound) 35 b = randint(1, bound) 36 fout.write("%d %d %d %d %d\n" % (u, v, k, a, b)) 37 38 39 def MovDataIn(): 40 desFileName = "F:\eclipse_prj\workspace\hdoj\data.in" 41 shutil.copyfile("data.in", desFileName) 42 43 44 if __name__ == "__main__": 45 GenDataIn() 46 MovDataIn()