Bzoj:1758:[Wc2010]重建計劃:樹的點分治

題目鏈接:[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);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章