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 }
View Code

 

posted @ 2019-01-17 19:55  Dup4  阅读(125)  评论(0编辑  收藏  举报