bzoj4326

Posted Kaiser

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4326相关的知识,希望对你有一定的参考价值。

运输计划

这是一道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 }

 

以上是关于bzoj4326的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4326: NOIP2015 运输计划

BZOJ 4326 NOIP2015 运输计划

BZOJ-4326运输计划 树链剖分 + 树上差分 + 二分

BZOJ 4326NOIP2015运输计划

BZOJ 4326 NOIP2015 运输计划

BZOJ 4326 树链剖分+二分+差分+记忆化