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 }

 

posted @ 2018-09-25 21:29  Ressed  阅读(175)  评论(0编辑  收藏  举报