題目鏈接:[Wc2010]重建計劃
純粹是爲了複習板子,也沒有什麼思考,感覺是糟蹋了這道題了……
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200010;
const int inf=1000000000;
const double eps=1e-4;
int n,m,s[maxn],dp[maxn],root,h[maxn];
struct edge{int to,next,w;}G[maxn*2];
int tot=1,fa[maxn],q[maxn],dq[maxn];
int size,deep[maxn],L,U,mx=0;
double dis[maxn],md[maxn],ans=0;
bool flag[maxn];
void add(int x,int y,int z){
G[++tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].w=z;
G[++tot].to=x;G[tot].next=h[y];h[y]=tot;G[tot].w=z;
}
void getroot(int x,int fa){
dp[x]=0; s[x]=1;
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (v==fa||flag[v]) continue;
getroot(v,x); s[x]+=s[v];
dp[x]=max(dp[x],s[v]);
}dp[x]=max(dp[x],size-s[x]);
if (dp[x]<dp[root]) root=x;
}
bool check(int rt,double mid){
int tmp=0;
for (int i=h[rt];i;i=G[i].next){
int v=G[i].to;
if (flag[v]) continue;
q[0]=v; int head=0,t=1;
fa[v]=root; deep[v]=1;
dis[v]=(double)G[i].w-mid;
while (head!=t){
int u=q[head]; head++;
for (int j=h[u];j;j=G[j].next){
int x=G[j].to;
if (x==fa[u]||flag[x]) continue;
q[t]=x; fa[x]=u; deep[x]=deep[u]+1;
dis[x]=dis[u]+G[j].w-mid; t++;
}
}
int l=1,r=0,now=tmp;
for (int j=0;j<t;++j){
int x=q[j];
while (deep[x]+now>=L&&now>=0){
while (l<=r&&md[dq[r]]<=md[now]) r--;
dq[++r]=now; now--;
}
while (l<=r&&deep[x]+dq[l]>U) l++;
if (l<=r&&dis[x]+md[dq[l]]>=0) return 1;
}
for (int j=tmp+1;j<=deep[q[t-1]];++j) md[j]=-inf;
for (int j=0;j<t;++j){
int x=q[j];
md[deep[x]]=max(md[deep[x]],dis[x]);
}
tmp=max(tmp,deep[q[t-1]]);
}return 0;
}
void calc(int x){
double l=ans,r=mx;
while (r-l>eps){
double mid=(l+r)/2;
if (check(x,mid)) l=mid;
else r=mid;
}ans=l;
}
void work(int x){
calc(x); flag[x]=1;
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (flag[v]) continue;
size=s[v];
getroot(v,root=0);
if (s[v]>L) work(root);
}
}
int main(){
scanf("%d%d%d",&n,&L,&U);
for (int i=1;i<n;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); mx=max(mx,z);
}
dp[0]=size=n; getroot(1,root=0);
work(root);
printf("%.3lf",ans);
}