zoukankan      html  css  js  c++  java
  • 「luogu2680」[NOIp2015] 运输计划

    题目大意:给定一棵n个节点的树,输入m组一条链的两个端点;把树上的某个边权改为0,求m条链长度的最大值的最小值;

    .考虑二分

      1.对于需要判断是否为可行方案的 mid,所有链长不大于 mid 的链不会造成影响;

      2.故只考虑链长大于 mid 的链是否可以 通过操作使它们的长度不超过mid;

      3.对于 2 显然可以得到一个充要条件 —— 存在至少一条边 被所有长度大于 mid 的链覆盖,

                          在满足上述条件的边中,至少存在一条边,其边权>=最长链的长度-mid

    .问题只剩下如何处理  一.3

      边权覆盖次数——树上差分(点权下放:将一条边被覆盖的次数 (即:在差分数组中的权值) 储存在它下方的点

        如何记录?—— diff [u] ++ , diff [v]++ , diff [ lca[(u,v)] -=2;

    代码如下:(这份代码有很多处理不当的地方,导致常数过大,如:最大链长只需处理一次,差分数组在计算时可记录 dfs 序通过一次循环处理等)

    p.s. :  一个奇技淫巧:求 lca 预处理时可能会因为碰到一条链导致爆栈,这时候,不如发挥我们天马行空的想象力,因为大部分人出的链数据都是1->2->3->4……所以把 n/2+1 作为根可以防止栈溢出 (详见luoguP2680)

      1 //Author : 15owzLy1
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <queue>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 #define lson tl, mid, rt<<1
     12 #define rson mid+1, tr, rt<<1|1
     13 #define pb(__) push_back(__)
     14 #define fr() front()
     15 #define bg() begin()
     16 #define it iterator
     17 #define INF 2100000000
     18 typedef long long ll;
     19 typedef double db;
     20 template<class T>inline void get_max(T &_, T __) { _=_>__?_:__; }
     21 template<class T>inline void get_min(T &_, T __) { _=_<__?_:__; }
     22 template<class T>inline void Swap(T &_, T &__) { T ___=_;_=__;__=___; }
     23 template<class T>inline T abs(T _) { return _>0?_:-_; }
     24 template<typename T>inline void read(T &_) {
     25     _=0;bool __=0;char ___=getchar();
     26     while(___<'0'||___>'9'){__|=(___=='-');___=getchar();}
     27     while(___>='0'&&___<='9'){_=(_<<1)+(_<<3)+(___^48);___=getchar();}
     28     _=__?-_:_;
     29 }
     30 
     31 const int N = 3000005;
     32 struct node {
     33     int next, to, len;
     34 }edge[N<<1];
     35 struct info {
     36     int l, r, lca;
     37 }q[N];
     38 int n, m, head[N], cnt=1, fa[N], dis[N], x, y, z, tot, rt;
     39 int dep[N], diff[N], front[N], size[N], hson[N];
     40 
     41 inline void add_Edge(int u, int v, int w) {
     42     edge[++cnt].to=v;
     43     edge[cnt].len=w;
     44     edge[cnt].next=head[u];
     45     head[u]=cnt;
     46 }
     47 
     48 //heavy-light decompostion begin
     49 void get_hson(int u) {
     50     size[u]=1;
     51     for(int i=head[u];i;i=edge[i].next) {
     52         int v=edge[i].to;
     53         if(fa[u]==v) continue;
     54         dep[v]=dep[u]+1, dis[v]=dis[u]+edge[i].len, fa[v]=u;
     55         get_hson(v);
     56         size[u]+=size[v];
     57         if(size[v]>size[hson[u]]) hson[u]=v;
     58     }
     59 }
     60 
     61 void get_front(int u, int father) {
     62     front[u]=father;
     63     if(hson[u]) get_front(hson[u], father);
     64     for(int i=head[u];i;i=edge[i].next) {
     65         int v=edge[i].to;
     66         if(fa[u]==v||hson[u]==v) continue;
     67         get_front(v, v);
     68     }
     69 }
     70 
     71 inline int lca(int u, int v) {
     72     while(front[u]!=front[v])
     73         if(dep[front[u]]>dep[front[v]]) u=fa[front[u]];
     74         else                            v=fa[front[v]];
     75     return dep[u]>dep[v]?v:u;
     76 }
     77 //heavy-light decompostion end
     78 
     79 //work begin
     80 void calc(int u, int &kk, int cnt) {
     81     for(int i=head[u];i;i=edge[i].next) {
     82         int v=edge[i].to, w=edge[i].len;
     83         if(v==fa[u]) continue;
     84         calc(v, kk, cnt);
     85         if(diff[v]>=cnt) get_max(kk, w);
     86         diff[u]+=diff[v];
     87     }
     88 }
     89 
     90 inline int check(int lim) {
     91     int max=0, cnt=0, max_edge=0;
     92     memset(diff, 0, sizeof(diff));
     93     for(int i=1;i<=m;i++)
     94         if(dis[q[i].l]+dis[q[i].r]-2*dis[q[i].lca]>lim) {
     95             ++cnt;
     96             diff[q[i].l]++, diff[q[i].r]++, diff[q[i].lca]-=2;
     97             get_max(max, dis[q[i].l]+dis[q[i].r]-2*dis[q[i].lca]);
     98         }
     99     calc(rt, max_edge, cnt);
    100     if(max-max_edge>lim)
    101         return false;
    102     return true;
    103 }
    104 
    105 inline int Binary_Search(int l, int r) {
    106     int ret=r, mid;
    107     while(l<=r) {
    108         mid=l+r>>1;
    109         if(check(mid)) ret=mid, r=mid-1;
    110         else           l=mid+1;
    111     }
    112     return ret;
    113 }
    114 //work end
    115 
    116 int main() {
    117     freopen("transport.in","r",stdin);
    118     freopen("transport.out","w",stdout);
    119     int max=0;
    120     read(n), read(m);
    121     for(int i=1;i<n;i++) {
    122         read(x), read(y), read(z);
    123         add_Edge(x, y, z), add_Edge(y, x, z);
    124     }
    125     rt=(n>>1)+1;
    126     dep[rt]=1; get_hson(rt); get_front(rt, rt);
    127     for(int i=1;i<=m;i++) {
    128         read(q[i].l), read(q[i].r);
    129         q[i].lca=lca(q[i].l, q[i].r);
    130         get_max(max, dis[q[i].l]+dis[q[i].r]-2*dis[q[i].lca]);
    131     }
    132     printf("%d
    ", Binary_Search(0, max));
    133     fclose(stdin);
    134     fclose(stdout);
    135     return 0;
    136 } 
    View Code
  • 相关阅读:
    菜鸟记录:如何获取LOGINVIEW控件状态模板中的子控件
    无法安装dotnetFramework35sp1的解决方法
    MOSS2007小技巧:不用SPD轻松删除错误页面上的问题Webpart
    在动态页面里象静态页面一样控制整个网页的缓存和更新
    烦人的网页iframe去除
    经典sql注入教程
    自己写的后台静态权限验证类
    Asp.net项目从Vs2003转换到Vs2005的常见问题大全及解决方法
    C# 相当于ASP里Eval中的计算公式的方法(超简单的方法)
    1 UNIX与Linux的发展
  • 原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/9889868.html
Copyright © 2011-2022 走看看