——————————————————————————————————————————————————————
邪门的贪心,需要处理很多情况,还要注意二分
还要注意标记下传
还要处理倍增
还要双指针
还是一道很好的题
——————————————————————————————————————
#include<bits/stdc++.h> using namespace std; struct node{int nxt,dis,to;}eg[51000*2]; #define ll long long int n,head[51000],m,ne,fa[51000][22],d[51000][22],a,b,c,id[51000],tag[51000]; void adde(int from,int to,int dis) {eg[++ne].to=to;eg[ne].dis=dis;eg[ne].nxt=head[from];head[from]=ne;} struct nd{int it,re;}num[51000]; struct nod{int ti,val;}q[51000]; int cmp(nd x,nd y){return x.re<y.re;} int cmp2(nod a,nod b){return a.val<b.val;} void dfs(int u,int f){ for(int i=head[u];i;i=eg[i].nxt) { int v=eg[i].to; if(v==f)continue; fa[v][0]=u;d[v][0]=eg[i].dis; dfs(v,u); } } void dfs2(int u,int f){ if(tag[u])return; bool flg=0;tag[u]=1; for(int i=head[u];i;i=eg[i].nxt) { int v=eg[i].to; if(v==f)continue; dfs2(v,u); flg=1; if(!tag[v])tag[u]=0; } if(!flg)tag[u]=0; } int check(ll w) { memset(tag,0,sizeof(tag)); int cnt=0,sum=0; for(int i=1;i<=m;i++) { ll rest=w; int di=id[i]; for(int j=16;j>=0;j--)if(rest-d[di][j]>=0&&fa[di][j]>1){rest-=d[di][j];di=fa[di][j];} if(fa[di][0]!=1||(rest<d[di][0]))tag[di]=1; else { num[++cnt].it=di; num[cnt].re=rest-d[di][0]; } } dfs2(1,1); for(int i=head[1];i;i=eg[i].nxt) if(!tag[eg[i].to]){q[++sum].ti=eg[i].to;q[sum].val=eg[i].dis;} sort(num+1,num+1+cnt,cmp); sort(q+1,q+1+sum,cmp2); int pos=1; for(int i=1;i<=cnt;++i) { if(!tag[num[i].it]) tag[num[i].it]=1; else if(num[i].re>=q[pos].val)tag[q[pos].ti]=1; while(tag[q[pos].ti]&&pos<=sum) ++pos; int t; for(t=pos;t<=sum;t++) { } } return pos>sum; } int main() { ll r=0,l=0,mid,ans; cin>>n; for(int i=1;i<n;i++) {cin>>a>>b>>c;adde(a,b,c);adde(b,a,c);r+=c;} cin>>m; for(int i=1;i<=m;i++)cin>>id[i]; dfs(1,0); for(int i=1;i<=16;i++)for(int j=1;j<=n;j++){fa[j][i]=fa[fa[j][i-1]][i-1];d[j][i]=d[j][i-1]+d[fa[j][i-1]][i-1]; } while(l<=r) { mid=(l+r)/2; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } cout<<ans; }