二分答案的做法放到树上呢
考虑线性数据上二分的完整做法
预处理每一条链的length,二分答案,放到check函数里搞
没问题
LCA求出每条链的length,还是二分,check函数换成树上差分
最后发现正解只要一句话:
求链长+二分
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=3e5+10; struct edge{ int next,to,dis; }e[2*maxn],q[2*maxn]; struct length{ int len,lca,u,v; }len[maxn]; int head[maxn],cnt,headq[maxn],dis[maxn],maxlen,n,m,a[maxn],ans,s[maxn],num,ret,f[maxn]; bool vis[maxn]; inline int readn() { int x=0; char ch=getchar(); while(ch>‘9‘||ch<‘0‘) ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) { x=(x<<3)+(x<<1)+(ch^‘0‘); ch=getchar(); } return x; } inline void add_edge(int x,int y,int d) { e[++cnt].next=head[x]; e[cnt].to=y; e[cnt].dis=d; head[x]=cnt; } inline void add_que(int x,int y) { q[++cnt].next=headq[x]; q[cnt].to=y; headq[x]=cnt; } int find(int x) { return f[x]==x?f[x]:f[x]=find(f[x]); } void dfs(int u,int pre) { for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==pre) continue; dfs(v,u); s[u]+=s[v]; } if(s[u]==num&&a[u]>ret) ret=a[u]; } inline bool check(int x) { memset(s,0,sizeof(s)); num=ret=0; for(int i=1;i<=m;i++) if(len[i].len>x) { s[len[i].u]++; s[len[i].v]++; s[len[i].lca]-=2; num++; } dfs(1,0); if(maxlen-ret>x) return 0; return 1; } void tarjan(int u,int pre) { for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==pre) continue; dis[v]=dis[u]+e[i].dis; tarjan(v,u); a[v]=e[i].dis; int f1=find(v); int f2=find(u); if(f1!=f2) f[f1]=find(f2); vis[v]=1; } for(int i=headq[u];i;i=q[i].next) if(vis[q[i].to]) { int p=(i+1)>>1; len[p].lca=find(q[i].to); len[p].len=dis[u]+dis[q[i].to]-2*dis[len[p].lca]; maxlen=max(maxlen,len[p].len); } } int main() { n=readn(),m=readn(); for(int i=1;i<n;i++) { int ai=readn(),bi=readn(),ti=readn(); add_edge(ai,bi,ti); add_edge(bi,ai,ti); } for(int i=1;i<=n;i++) f[i]=i; cnt=0; for(int i=1;i<=m;i++) { int x=readn(),y=readn(); len[i].u=x; len[i].v=y; add_que(x,y); add_que(y,x); } tarjan(1,0); int l=0,r=maxlen,mid; while(l<=r) { mid=(l+r)>>1; if(check(mid)) { r=mid-1; ans=mid; } else l=mid+1; } printf("%d\n",ans); return 0; }
原文:https://www.cnblogs.com/ainiyuling/p/11458572.html