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

    还留有倍增的痕迹。

  • 相关阅读:
    java中Executor、ExecutorService、ThreadPoolExecutor介绍
    JAVA多线程实现的四种方式
    JVM内存结构
    Synchronized修饰静态变量和普通变量的区别
    tcpkill工作原理分析
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    数据库路由中间件MyCat
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6924331.html
Copyright © 2011-2022 走看看