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的主要内容,如果未能解决你的问题,请参考以下文章