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 }
  • 相关阅读:
    ASP.NET在禁用视图状态的情况下仍然使用ViewState对象【转】
    Atcoder Regular Contest 061 D Card Game for Three(组合数学)
    Solution 「CERC 2016」「洛谷 P3684」机棚障碍
    Solution 「CF 599E」Sandy and Nuts
    Solution 「洛谷 P6021」洪水
    Solution 「ARC 058C」「AT 1975」Iroha and Haiku
    Solution 「POI 2011」「洛谷 P3527」METMeteors
    Solution 「CF 1023F」Mobile Phone Network
    Solution 「SP 6779」GSS7
    Solution 「LOCAL」大括号树
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7465120.html
Copyright © 2011-2022 走看看