zoukankan      html  css  js  c++  java
  • BZOJ4326: NOIP2015 运输计划

    从题解里看到了二分才想到二分

    题意为:给出一棵树和一些路线,要求你选树上一条边边权变为0后,路线中最大值最小

    显然答案有单调性,二分答案

    将所有长度超过 mid 的路径在树上标记出来,找出一条被所有的标记路径覆盖的边,当前答案合法条件为:max_path - maxlen <= mid

    显然上边的操作可以树上差分,预处理每条路径端点的 lca 即可做到 O(n) 判断

    这个 O(n) 大概是 2n ,卡卡常就好了


    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cstdio>
    using namespace std;
    
    const int MAXN = 300005;
    
    struct EDGE{
      int nxt, to, val;
      EDGE(int NXT = 0, int TO = 0, int VAL = 0) {nxt = NXT; to = TO; val = VAL;}
    }edge[MAXN << 1];
    struct QUE{
      int x, y, lca, dst;
    }que[MAXN];
    int n, m, totedge, mxl, mnl = 0x7fffffff;
    int head[MAXN], dst[MAXN], tag[MAXN], top[MAXN];
    int dep[MAXN], siz[MAXN], son[MAXN], fa[MAXN];
    
    inline int rd() {
      register int x = 0;
      register char c = getchar();
      while(!isdigit(c)) c = getchar();
      while(isdigit(c)) {
        x = x * 10 + (c ^ 48);
        c = getchar();
      }
      return x;
    }
    inline int mx(int x, int y) {
      return (x > y ? x : y);
    }
    inline int mn(int x, int y) {
      return (x > y ? y : x);
    }
    void gfs(int x) {
      siz[x] = 1;
      for(int i = head[x]; i; i = edge[i].nxt) if(edge[i].to != fa[x]) {
        int y = edge[i].to;
        dep[y] = dep[x] + 1;
        dst[y] = dst[x] + edge[i].val;
        fa[y] = x;
        gfs(y);
        siz[x] += siz[y];
        if(siz[y] > siz[son[x]]) son[x] = y;
      }
      return;
    }
    void ifs(int x) {
      if(!top[x]) top[x] = x;
      if(son[x]) {
        top[son[x]] = top[x];
        ifs(son[x]);
      }
      for(int i = head[x]; i; i = edge[i].nxt) if(edge[i].to != son[x] && edge[i].to != fa[x]) ifs(edge[i].to);
      return;
    }
    inline int lca(int x, int y) {
      while(top[x] != top[y]) {
        if(dep[top[x]] < dep[top[y]]) swap(x, y);
        x = fa[top[x]];
      }
      return (dep[x] > dep[y] ? y : x);
    }
    int dfs(int x, int tot, int frm) {
      int maxlen = 0;
      for(int i = head[x]; i; i = edge[i].nxt) if(fa[x] != edge[i].to) {
          maxlen = max(maxlen, dfs(edge[i].to, tot, i));
          tag[x] += tag[edge[i].to];
      }
      return (tag[x] == tot) ? (mx(maxlen, edge[frm].val)) : maxlen;
    }
    inline bool chk(int mid) {
      register int tot = 0, maxlen = 0;
      register bool extra = false;
      for(int i = 1; i <= n; ++i) tag[i] = 0;
      for(int i = 1; i <= m; ++i) {
        if(que[i].dst > mid) {
          maxlen = mx(maxlen,que[i].dst);
          ++tot;
          ++tag[que[i].x]; ++tag[que[i].y];
          tag[que[i].lca] -= 2;
          extra = true;
        }
      }
      if(!extra) return true;
      return (maxlen - dfs(1, tot, 0) <= mid);
    }
    inline void hfs(int l, int r) {
      int mid = 0, ans = 0;
      while(l < r) {
        mid = ((l + r) >> 1);
        if(chk(mid)) {
          ans = mid;
          r = mid;
        }
        else l = mid + 1;
      }
      printf("%d
    ", ans);
      return;
    }
    
    int main() {
      //  freopen("testdata1.in", "r", stdin);
      n = rd(); m = rd();
      register int xx, yy, vv, tmp, N;
      tmp = (n - 1) & 1; N = n - 1 - tmp;
     //printf("tmp = %d, N = %d
    ", tmp, N);
      for(int i = 1; i <= N; i += 2) {
      //	printf("i = %d
    ", i);
      //	printf("totedge = %d
    ", totedge);
        xx = rd(); yy = rd(); vv = rd();
        mnl = mn(mnl,vv);
    	edge[++totedge] = EDGE(head[xx], yy, vv);
    	head[xx] = totedge;
    	edge[++totedge] = EDGE(head[yy], xx, vv);
    	head[yy] = totedge;
        xx = rd(); yy = rd(); vv = rd();
        mnl = mn(mnl,vv);
    	edge[++totedge] = EDGE(head[xx], yy, vv);
    	head[xx] = totedge;
    	edge[++totedge] = EDGE(head[yy], xx, vv);
    	head[yy] = totedge;
    //	printf("totedge = %d
    ", totedge);
      }
      for(int i = 1; i <= tmp; ++i) {
        xx = rd(); yy = rd(); vv = rd();
        mnl = mn(mnl,vv);
    	edge[++totedge] = EDGE(head[xx], yy, vv);
    	head[xx] = totedge;
    	edge[++totedge] = EDGE(head[yy], xx, vv);
    	head[yy] = totedge;
      }
      dst[1] = 0; dep[1] = 1;
      gfs(1);
      ifs(1);
      for(int i = 1; i <= m; ++i) {
        que[i].x = rd(); que[i].y = rd();
        que[i].lca = lca(que[i].x, que[i].y);
        que[i].dst = dst[que[i].x] + dst[que[i].y] - (dst[que[i].lca] << 1);
        mxl = mx(mxl,que[i].dst);
      }
      hfs(mnl, mxl);
      return 0;
    }
    

      

    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    Android启动报错:install failed invalid apk
    一个资源丰富的在线小程序社区推荐
    一个好用的在线微信二维码设计网站
    一个资源丰富的在线小程序社区推荐
    百度地图API的使用示例
    百度地图API的使用示例
    vue.js提交按钮时简单的if判断表达式示例
    vue.js代码开发最常见的功能集合
    如何运行vue项目(维护他人的项目)
    ES6-----学习系列七(函数扩展)
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9570632.html
Copyright © 2011-2022 走看看