BZOJ 2599: [IOI2011]Race
点分治,定权值,求另一关键字最小
不满足前缀加减性
可以按序遍历,用一数组$t[] 来维护路径为i的最小边数$
再对于一个直系儿子对应的子树,先算距离求答案再更新$t数组,这样就不会重复$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 200010 5 #define M 1000010 6 #define INF 0x3f3f3f3f 7 int n, k; 8 struct Graph 9 { 10 struct node 11 { 12 int to, nx, w; 13 node() {} 14 node(int to, int nx, int w) : to(to), nx(nx), w(w) {} 15 }a[N << 1]; 16 int head[N], pos; 17 void init() 18 { 19 memset(head, 0, sizeof head); 20 pos = 0; 21 } 22 void add(int u, int v, int w) 23 { 24 a[++pos] = node(v, head[u], w); head[u] = pos; 25 a[++pos] = node(u, head[v], w); head[v] = pos; 26 } 27 }G; 28 #define erp(u) for (int it = G.head[u], v = G.a[it].to, w = G.a[it].w; it; it = G.a[it].nx, v = G.a[it].to, w = G.a[it].w) 29 30 int vis[N]; 31 int sum, root, sze[N], f[N]; 32 void getroot(int u, int fa) 33 { 34 f[u] = 0, sze[u] = 1; 35 erp(u) if (v != fa && !vis[v]) 36 { 37 getroot(v, u); 38 sze[u] += sze[v]; 39 f[u] = max(f[u], sze[v]); 40 } 41 f[u] = max(f[u], sum - sze[u]); 42 if (f[u] < f[root]) root = u; 43 } 44 45 int dist[N], deep[N], t[M], res; 46 void getdeep(int u, int fa) 47 { 48 if (dist[u] <= k) res = min(res, deep[u] + t[k - dist[u]]); 49 erp(u) if (v != fa && !vis[v]) 50 { 51 dist[v] = dist[u] + w; 52 deep[v] = deep[u] + 1; 53 getdeep(v, u); 54 } 55 } 56 57 void add(int u, int fa, int flag) 58 { 59 if (dist[u] <= k) 60 { 61 if (flag) t[dist[u]] = min(t[dist[u]], deep[u]); 62 else t[dist[u]] = INF; 63 } 64 erp(u) if (v != fa && !vis[v]) 65 add(v, u, flag); 66 } 67 68 void solve(int u) 69 { 70 vis[u] = 1; t[0] = 0; 71 erp(u) if (!vis[v]) 72 { 73 deep[v] = 1, dist[v] = w; 74 getdeep(v, u); add(v, u, 1); 75 } 76 erp(u) if (!vis[v]) add(v, u, 0); 77 erp(u) if (!vis[v]) 78 { 79 sum = f[0] = sze[v]; root = 0; 80 getroot(v, 0); 81 solve(root); 82 } 83 } 84 85 void Run() 86 { 87 while (scanf("%d%d", &n, &k) != EOF) 88 { 89 G.init(); res = INF; 90 memset(t, 0x3f, sizeof t); 91 for (int i = 1, u, v, w; i < n; ++i) 92 { 93 scanf("%d%d%d", &u, &v, &w); 94 ++u, ++v; 95 G.add(u, v, w); 96 } 97 sum = f[0] = n; root = 0; 98 getroot(1, 0); 99 solve(root); 100 printf("%d\n", res == INF ? -1 : res); 101 } 102 } 103 104 int main() 105 { 106 #ifdef LOCAL 107 freopen("Test.in", "r", stdin); 108 #endif 109 110 Run(); 111 return 0; 112 }