zoukankan      html  css  js  c++  java
  • bzoj4326 [NOIP2015]运输计划

    运输计划

    这是一道2015年NOIP提高组的最后一题。

    这道题,不看题解之间只有一点思路,没想到差分,这个是真的,这道题就是求出各点对之间路径权值和,怎么求路径和呢,就是可以

    用lca的方式,求出,然后枚举答案,二分枚举,因为这个题目具有二分性质,

    然后就是用差分思想,就是在A,B儿子上加1,然后lca(A,B)上-2,然后统计哪些边超过了枚举值,然后

    就是统计,很简单的,注释在代码上好了。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<algorithm>
      6 
      7 using namespace std;
      8 const int P=16;
      9 const int N=300007;
     10 
     11 int n,m,l,r;
     12 int cnt,head[N],rea[N*2],Next[N*2],val[N*2];
     13 int LCA[N],dis_total[N];
     14 int deep[N],anc[N][P+5];
     15 int fa[N],dis[N],sum[N],vv[N],B[N],A[N];
     16 
     17 void add(int u,int v,int fee)
     18 { 
     19     cnt++;
     20     Next[cnt]=head[u];
     21     head[u]=cnt;
     22     rea[cnt]=v;
     23     val[cnt]=fee;
     24 }
     25 void dfs(int u,int f)
     26 {
     27     anc[u][0]=fa[u]=f;
     28     for(int p=1;p<=P;p++)
     29         anc[u][p]=anc[anc[u][p-1]][p-1];
     30     for(int t=head[u];t;t=Next[t])
     31     {
     32         int v=rea[t];
     33         if(v==f) continue;
     34         deep[v]=deep[u]+1;
     35         vv[v]=val[t];
     36         dis[v]=dis[u]+val[t];
     37         dfs(v,u);
     38     }
     39 }
     40 int lca( int u,int v)
     41 {
     42     if(deep[u]<deep[v])swap(u,v);
     43     int t=deep[u]-deep[v];
     44     for(int p=0;t;t>>=1,p++)
     45         if( t&1)u=anc[u][p];
     46     if(u==v) return u;
     47     for(int p=P;p>=0;p--) 
     48         if(anc[u][p]!=anc[v][p])
     49             u=anc[u][p],v=anc[v][p];
     50     return anc[u][0];
     51 }
     52 void pus(int x,int fa)
     53 {
     54     for(int i=head[x];i;i=Next[i])
     55     {
     56         int v=rea[i];
     57         if(v!=fa)
     58         {
     59             pus(v,x);
     60             sum[x]+=sum[v];
     61         }
     62     }//统计sum 
     63 }
     64 bool check(int x)
     65 {
     66     int cont=0,mx=0;
     67     for(register int i=1;i<=n;i++) 
     68         sum[i]=0;
     69     for(int i=1;i<=m;i++)
     70         if(dis_total[i]>x)
     71         {
     72             cont++;
     73             sum[B[i]]++,sum[A[i]]++; 
     74             sum[LCA[i]]-=2;
     75             mx=max(mx,dis_total[i]-x);
     76         }
     77     pus(1,0);
     78     for(int i=1;i<=n;i++) 
     79         if (sum[i]==cont&&vv[i]>=mx) return true;//vv[i]表示v->u的距离,然后mx表示相差的最大距离。 
     80     return false;
     81 }
     82 void init()
     83 {
     84     scanf("%d%d",&n,&m);
     85     for(int i=1;i<n;i++)
     86     {
     87         int u,v,w;
     88         scanf("%d%d%d",&u,&v,&w);
     89         add(u,v,w),add(v,u,w);
     90     }
     91     deep[1]=1;
     92     dfs(1,1);
     93     
     94     for(int i=1;i<=m;i++)
     95     {
     96         scanf("%d%d",&A[i],&B[i]);
     97         LCA[i]=lca(A[i],B[i]);//倍增求lca。 
     98         dis_total[i]=dis[A[i]]+dis[B[i]]-2*dis[LCA[i]];
     99         r=max(r,dis_total[i]);
    100     }
    101 }
    102 int main()
    103 {
    104     init();
    105     while(l<r)
    106     {
    107         int mid=(l+r)>>1;
    108         if(check(mid)) r=mid;
    109         else l=mid+1;
    110     }
    111     printf("%d",l);
    112 }
  • 相关阅读:
    Java设计模式-----装饰模式
    Java并发包中Lock的实现原理
    ThreadLocal,静态变量,实例变量,局部变量的线程安全
    ThreadLocal类详解
    SQL之LEFT JOIN,EIGHT JOIN,INSERT JOIN的区别
    Wireshark 、HTTPWatch、Fiddler的介绍
    TCP/IP、HTTP、Socket的区别
    我希望你并不幸福
    Autoregressive Convolutional Neural Networks for Asynchronous Time Series
    DRL Lecture1:Policy Gradient
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7465120.html
Copyright © 2011-2022 走看看