zoukankan      html  css  js  c++  java
  • [luoguP2680] 运输计划(lca + 二分 + 差分)

    传送门

    暴力做法 50 ~ 60

    枚举删边,求最大路径长度的最小值。

    其中最大路径长度运用到了lca

    我们发现,求lca的过程已经不能优化了,那么看看枚举删边的过程能不能优化。

    先把边按照权值排序,然后。。。

    然而并没有什么卵用。

    题解给出了一种二分

    二分答案。

    判断依据:

    比当前答案大的路径长度如果有一个公共边,并且最大的路径减去这条公共边小于等于当前答案,那么当前答案就满足。

    如果当前答案不满足,那么比他小的答案更不可能满足,因为都不小于等于当前答案,比当前答案小的更不可能。

    接下来就是如何判断,num[i] 表示点 i 指向父亲的边被几条路径所共有。

    那么只需要 num[x]++, num[y]++, num[lca(x, y)] -= 2

    最后dfs一遍求树上前缀和即可。

    然后在 (num[i] == 比当前答案大的边的条数) 中找最大的边

    然后判断就可以了

    但是就是一个点超时,无语,把倍增改成tarjan也是超时,蛋疼。

    ——代码

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #define max(x, y) ((x) > (y) ? (x) : (y))
      6 #define MAXN 300001
      7 
      8 int n, m, cnt, qcnt;
      9 int num[MAXN], dis[MAXN], fv[MAXN], fa[MAXN], f[MAXN];
     10 int head[MAXN], to[MAXN << 1], val[MAXN << 1], next[MAXN << 1], qhead[MAXN], qnext[MAXN << 1], qto[MAXN << 1];
     11 //int f[MAXN][21], deep[MAXN];
     12 
     13 struct node
     14 {
     15     int qx, qy, lca, v;
     16 }q[MAXN];
     17 
     18 inline int read()
     19 {
     20     int x = 0, f = 1;
     21     char ch = getchar();
     22     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
     23     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
     24     return x * f;
     25 }
     26 
     27 inline void add(int x, int y, int z)
     28 {
     29     to[cnt] = y;
     30     val[cnt] = z;
     31     next[cnt] = head[x];
     32     head[x] = cnt++;
     33 }
     34 
     35 inline void addq(int x, int y)
     36 {
     37     qto[qcnt] = y;
     38     qnext[qcnt] = qhead[x];
     39     qhead[x] = qcnt++;
     40 }
     41 
     42 /*inline void dfs(int u)
     43 {
     44     int i, v;
     45     deep[u] = deep[f[u][0]] + 1;
     46     for(i = 0; f[u][i]; i++) f[u][i + 1] = f[f[u][i]][i];
     47     for(i = head[u]; i ^ -1; i = next[i])
     48     {
     49         v = to[i];
     50         if(!deep[v]) fv[v] = val[i], dis[v] = dis[u] + val[i], f[v][0] = u, dfs(v);
     51     }
     52 }
     53 
     54 inline int Lca(int x, int y)
     55 {
     56     int i;
     57     if(deep[x] < deep[y]) x ^= y ^= x ^= y;
     58     for(i = 18; i >= 0; i--)
     59         if(deep[f[x][i]] >= deep[y])
     60             x = f[x][i];
     61     if(x == y) return x;
     62     for(i = 18; i >= 0; i--)
     63         if(f[x][i] ^ f[y][i])
     64             x = f[x][i], y = f[y][i];
     65     return f[x][0];
     66 }*/ 
     67 
     68 inline int find(int x)
     69 {
     70     return x == fa[x] ? x : fa[x] = find(fa[x]);
     71 }
     72 
     73 inline void dfs(int u)
     74 {
     75     int i, v, x;
     76     fa[u] = u;
     77     for(i = head[u]; i ^ -1; i = next[i])
     78     {
     79         v = to[i];
     80         if(f[u] ^ v) f[v] = u, dis[v] = dis[u] + val[i], fv[v] = val[i], dfs(v);
     81     }
     82     for(i = qhead[u]; i ^ -1; i = qnext[i])
     83     {
     84         v = qto[i];
     85         if(f[x = u ^ q[v].qx ^ q[v].qy] || x == 1) q[v].lca = find(x);
     86     }
     87     fa[u] = f[u];
     88 }
     89 
     90 inline void dfs1(int u)
     91 {
     92     int i, v;
     93     for(i = head[u]; i ^ -1; i = next[i])
     94     {
     95         v = to[i];
     96         if(v ^ f[u]) dfs1(v), num[u] += num[v];
     97     }
     98 }
     99 
    100 inline bool pd(int sum)
    101 {
    102     int i, x = 1, y = m, mid, ans, value = 0;
    103     memset(num, 0, sizeof(num));
    104     while(x <= y)
    105     {
    106         mid = (x + y) >> 1;
    107         if(q[mid].v <= sum) x = mid + 1;
    108         else ans = mid, y = mid - 1;
    109     }
    110     for(i = ans; i <= m; i++) num[q[i].qx]++, num[q[i].qy]++, num[q[i].lca] -= 2;
    111     dfs1(1);
    112     for(i = 1; i <= n; i++)
    113         if(num[i] == m - ans + 1)
    114             value = max(value, fv[i]);
    115     if(!value) return 0;
    116     return q[m].v - value <= sum;
    117 }
    118 
    119 inline bool cmp(node x, node y)
    120 {
    121     return x.v < y.v;
    122 }
    123 
    124 int main()
    125 {
    126     int i, x, y, z, mid, ans = 0;
    127     n = read();
    128     m = read();
    129     memset(head, -1, sizeof(head));
    130     memset(qhead, -1, sizeof(qhead));
    131     for(i = 1; i < n; i++)
    132     {
    133         x = read();
    134         y = read();
    135         z = read();
    136         add(x, y, z);
    137         add(y, x, z);
    138     }
    139     //dfs(1);
    140     for(i = 1; i <= m; i++)
    141     {
    142         q[i].qx = read();
    143         q[i].qy = read();
    144         addq(q[i].qx, i);
    145         addq(q[i].qy, i);
    146         //q[i].lca = Lca(q[i].qx, q[i].qy);
    147         //q[i].v = dis[q[i].qx] + dis[q[i].qy] - (dis[q[i].lca] << 1);
    148     }
    149     dfs(1);
    150     x = y = 0;
    151     for(i = 1; i <= m; i++) q[i].v = dis[q[i].qx] + dis[q[i].qy] - (dis[q[i].lca] << 1), y = max(y, q[i].v);
    152     std::sort(q + 1, q + m + 1, cmp);
    153     while(x <= y)
    154     {
    155         mid = (x + y) >> 1;
    156         if(pd(mid)) ans = mid, y = mid - 1;
    157         else x = mid + 1;
    158     }
    159     printf("%d
    ", ans);
    160     return 0;
    161 }
    View Code

    还留有倍增的痕迹。

  • 相关阅读:
    BestCoder17 1001.Chessboard(hdu 5100) 解题报告
    codeforces 485A.Factory 解题报告
    codeforces 485B Valuable Resources 解题报告
    BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
    codeforces 374A Inna and Pink Pony 解题报告
    codeforces 483B Friends and Presents 解题报告
    BestCoder15 1002.Instruction(hdu 5083) 解题报告
    codeforces 483C.Diverse Permutation 解题报告
    codeforces 483A. Counterexample 解题报告
    NSArray中地内存管理 理解
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6924331.html
Copyright © 2011-2022 走看看