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

    花了两天终于A掉了这个题

    从这个题里学会了树上差分/前缀和这个神奇的东西

    觉得在树上弄区间问题树上差分和树上前缀和很有用

    代码如下(被洛谷卡常T了一个点,然后把二分的max调小,卡过去了)

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define MAXN 310000
    using namespace std; 
    
    struct edge {
      int e, v, next; 
    } E[2*MAXN]; 
    int e_cnt; 
    
    int s[MAXN], e[MAXN], r[MAXN], len[MAXN]; 
    int f[MAXN][20]; 
    int fa[MAXN]; 
    int dep[MAXN]; 
    int N, M; 
    int G[MAXN]; 
    int sum[MAXN]; 
    int cnt[MAXN]; 
    int lim, maxdist; 
    
    #define add(ss, ee, vv) do {            
        E[++e_cnt].e = ee; E[e_cnt].v = vv;        
        E[e_cnt].next = G[ss];            
        G[ss] = e_cnt;                
      } while(0)
    void build(int now, int deep) {
      dep[now] = deep; 
      for(int i = G[now]; i != 0; i = E[i].next) {
        if(E[i].e != fa[now]) {
          fa[E[i].e] = now; 
          sum[E[i].e] = sum[now]+E[i].v; 
          f[E[i].e][1] = now; 
          build(E[i].e, deep+1); 
        }
      }
    }
    void LCA_init() {
      for(int k = 2; k <= 20; k++)
        for(int i = 1; i <= N; i++)
          f[i][k] = f[f[i][k-1]][k-1]; 
    }
    int LCA(int aa, int bb) {
      register int i, a = aa, b = bb; 
      if(dep[a] < dep[b]) swap(a, b); 
      for(i = 20; dep[a] > dep[b]; i--) if(f[a][i] && dep[f[a][i]] >= dep[b]) a = f[a][i]; 
      if(a == b) return a; 
      for(i = 20; i >= 0; i--)
        if(f[a][i] != f[b][i]) {
          a = f[a][i]; 
          b = f[b][i]; 
        }
      return f[a][1]; 
    }
    void dfs(int now) {
      for(int i = G[now]; i != 0; i = E[i].next) {
        if(E[i].e != fa[now]) {
          dfs(E[i].e); 
          cnt[now] += cnt[E[i].e]; 
        }
      }
    }
    
    bool judge() {
      int c = 0, maxedge = 0, i; 
      memset(cnt, 0, sizeof(cnt)); 
      for(i = 1; i <= M; i++) 
        if(len[i] > lim) 
          c++, cnt[s[i]]++, cnt[e[i]]++, cnt[r[i]] -= 2;  
      dfs(1); 
      for(i = 1; i <= N; i++)
        if(cnt[i] >= c) 
          maxedge = max(maxedge, sum[i]-sum[fa[i]]); 
      if(maxdist > lim+maxedge) return false; 
      return true; 
    }
    
    int main() {
      int i, j; 
      int ss, ee, vv; 
      scanf("%d%d", &N, &M); 
      for(i = 1; i <= N-1; i++) {
        scanf("%d%d%d", &ss, &ee, &vv); 
        add(ss, ee, vv); add(ee, ss, vv); 
      }
      build(1, 1); 
      LCA_init(); 
      for(i = 1; i <= M; i++) {
        scanf("%d%d", &s[i], &e[i]); 
        r[i] = LCA(s[i], e[i]); 
        len[i] = sum[s[i]]+sum[e[i]]-2*sum[r[i]]; 
        maxdist = max(maxdist, len[i]); 
      }
      int start = 0, mid, end = 157654321; 
      while(start < end-1) {
        lim = mid = (start+end)/2; 
        if(judge() == false) start = mid+1; 
        else end = mid; 
      }
      lim = start; 
      if(judge() == false) printf("%d
    ", end); 
      else printf("%d
    ", start); 
      return 0; 
    }
  • 相关阅读:
    在controller的action内, 得到用户发过来的请求地址和参数url
    php Connection timed out after 30000 milliseconds
    htmlspecialchars_decode 解决掉 &amp;
    max_spare_servers到底是个什么意思?
    mysql 不同条件count ,多条件count()
    阿里云centOS7.4 ftp连接不上的问题
    阿里云 导入自定义的镜像
    thinkphp3.2.3 + nginx 配置二级域名
    FlashFXP客户端 FTP连接,连接很慢的情况,
    PHP对象的使用,什么时候可以用中括号[], 什么时候可以用箭头->
  • 原文地址:https://www.cnblogs.com/euphoria-eden/p/7656784.html
Copyright © 2011-2022 走看看