luogu2680 [NOIp2015]运输计划 (tarjanLca+二分答案+树上差分)
我们先不会就二分一下答案,设它是x,我们要判断它能不能满足
为了满足这个答案,我们就要让原本路径长度大于x的所有路径都经过某条边,而且这条边还要大于等于最长的路径-x
于是运用树上差分的思想,对于所有长度>x的路径,给他的两端点处++,lca处--,这样统计树上每个点的子树的和,就是这个点与它父节点连边被经过的次数
拿被经过次数>=长度大于x的路径条数的边 取一取最大值 然后判一判就行了
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=3e5+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 struct Edge{ 16 int b,l,ne; 17 }eg[maxn*2],que[maxn*2]; 18 int N,M; 19 int egh[maxn],ect,qh[maxn],lca[maxn],bfa[maxn]; 20 int dis[maxn],sum[maxn],ml,len[maxn]; 21 bool flag[maxn]; 22 23 inline void adeg(int a,int b,int l){ 24 eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect; 25 } 26 inline int getf(int x){return x==bfa[x]?x:bfa[x]=getf(bfa[x]);} 27 28 void tarjan(int x){ 29 flag[x]=1; 30 for(int i=egh[x];i;i=eg[i].ne){ 31 int b=eg[i].b;if(flag[b]) continue; 32 dis[b]=dis[x]+eg[i].l;tarjan(b); 33 bfa[getf(b)]=getf(x); 34 } 35 for(int i=qh[x];i;i=que[i].ne){ 36 int b=que[i].b;if(!flag[b]) continue; 37 lca[i>>1]=getf(b); 38 } 39 } 40 41 void dfs(int x,int f,int n){ 42 for(int i=egh[x];i;i=eg[i].ne){ 43 int b=eg[i].b;if(b==f) continue; 44 dfs(b,x,n);sum[x]+=sum[b]; 45 } 46 if(sum[x]>=n) ml=max(ml,dis[x]-dis[f]); 47 } 48 49 inline bool judge(int m){ 50 int c=0,mm=0; 51 memset(sum,0,sizeof(sum)); 52 for(int i=1;i<=M;i++){ 53 if(len[i]>m){ 54 c++,mm=max(mm,len[i]); 55 sum[que[i<<1].b]++;sum[que[i<<1|1].b]++; 56 sum[lca[i]]-=2; 57 } 58 } 59 ml=0;dfs(1,0,c); 60 return mm-ml<=m; 61 } 62 63 int main(){ 64 //freopen(".in","r",stdin); 65 int i,j,k; 66 N=rd(),M=rd(); 67 for(i=1;i<N;i++){ 68 int a=rd(),b=rd(),c=rd(); 69 adeg(a,b,c);adeg(b,a,c); 70 } 71 for(i=1;i<=M;i++){ 72 int a=rd(),b=rd(); 73 que[i<<1].b=b;que[i<<1].ne=qh[a];qh[a]=i<<1; 74 que[i<<1|1].b=a;que[i<<1|1].ne=qh[b];qh[b]=i<<1|1; 75 } 76 for(i=1;i<=N;i++) bfa[i]=i; 77 tarjan(1); 78 int mil=3e8,mal=0; 79 for(i=1;i<=M;i++){ 80 len[i]=dis[que[i<<1].b]+dis[que[i<<1|1].b]-2*dis[lca[i]]; 81 mil=min(mil,len[i]);mal=max(mal,len[i]); 82 } 83 int l=max(mil-1000,0),r=mal,ans; 84 while(l<=r){ 85 int m=l+r>>1; 86 if(judge(m)) ans=m,r=m-1; 87 else l=m+1; 88 } 89 printf("%d\n",ans); 90 return 0; 91 }