wc2010 bzoj1758(点分治+二分+单调队列) TLE

本文介绍了一种基于图的遍历与搜索算法实现方法,包括如何构建图数据结构、进行深度优先搜索与广度优先搜索等核心操作,并通过具体案例展示了算法的应用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 本机测试没有问题,提交tle

 

 updata 2017 4 2 tle ing

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<queue>
using namespace std;
const int N=100005;
inline int read()
{
    int ans;char ch;
    while ((ch=getchar())<'0'||ch>'9') ;ans=ch-'0';
    while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
    return ans;
}




int n,L,R;

int head[N],tot;
struct aa
{
	int to,pre;double dis;
}edge[N*2];
void addedge(int u,int v,double d)
{
	edge[++tot].to=v;edge[tot].pre=head[u];edge[tot].dis=d;head[u]=tot;
}
bool vis[N],b[N];
int size[N],sum,mi,rt;
void get_size(int u,int fa)
{
    size[u]=1;
    for (int i=head[u];i;i=edge[i].pre)
    if (!vis[edge[i].to]&&edge[i].to!=fa) 
    {
        get_size(edge[i].to,u);
        size[u]+=size[edge[i].to];
    }
}
void get_rt(int u,int fa)
{
    int mx=sum-size[u];
    for (int i=head[u];i;i=edge[i].pre)
    if (!vis[edge[i].to]&&edge[i].to!=fa)
    {
        get_rt(edge[i].to,u);
        mx=max(mx,size[edge[i].to]);
    }
    if (mx<mi) mi=mx,rt=u;
}
///////////////////////

int dep[N];double dis[N],MX=0,ans=1e9;
int q[N],hd,tl;
void bfs(double mid)
{
	while (hd<=tl)
	{
		if (dep[hd]==R) break;
		for (int v,i=head[q[hd]];i;i=edge[i].pre)
		if (!vis[v=edge[i].to]&&!b[v])
		{
			b[v]=true;
			q[++tl]=v;
			dep[tl]=dep[hd]+1;
			dis[tl]=dis[hd]+edge[i].dis-mid;
		}
		hd++;
	}
}
int ll,rr,id[N],begin,end;
double f[N],s[N];
bool pan(int rt,double mid)
{
	double ans=-1e9;
	
	int mx=0;
	for (int i=1;i<=size[rt];i++) f[i]=-1e9;f[0]=0;
	
	for (int u,i=head[rt];i;i=edge[i].pre) 
	if (!vis[u=edge[i].to])
	{
		q[hd=tl=1]=u;
		dep[hd]=1,dis[hd]=edge[i].dis-mid;b[u]=true;
		bfs(mid);
		
		ll=rr=min(mx,R+1);
		s[begin=end=1]=f[rr],id[begin]=rr;
		
		for (int j=1;j<=tl;j++)
		{
			if (dep[j]+ll<L) continue;
			while (dep[j]+ll>L&&ll>0)
			{
				ll--;
				while (f[ll]>s[end]&&begin<=end) end--;
				s[++end]=f[ll];id[end]=ll;
			}
			while (dep[j]+rr>R) rr--;
			while (id[begin]>rr) begin++;
			ans=max(ans,s[begin]+dis[j]);
		}
		for (int j=1;j<=tl;j++) f[dep[j]]=max(f[dep[j]],dis[j]),b[q[j]]=false;
		mx=max(mx,size[u]);
	}
	return ans>0;
}
void work(int u)
{
	double mid,l=ans,r=MX;
	while (l+0.0002<r) 
	{
		mid=(l*3+r)/4;
		if (pan(u,mid)) l=mid;else r=mid;
	}
	ans=l;
}
///////////////////////
void dfs(int u)
{
    get_size(u,0);sum=size[u];mi=1e9;
    get_rt(u,0);u=rt;
    if (sum<=L) return ;
    
	vis[u]=true;
    work(u);
    
    for (int i=head[u];i;i=edge[i].pre)
    if (!vis[edge[i].to]) dfs(edge[i].to);
}
int main()
{
	n=read(),L=read(),R=read();
	int u,v,d;
	for (int i=1;i<n;i++)
	{
		u=read(),v=read(),d=read();
		addedge(u,v,d);
		addedge(v,u,d);
		MX=max(MX,double(d));
		ans=min(ans,double(d));
	}
	dfs(1);
	printf("%.3lf",ans);
	return 0;
}


 

 

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1000005;



int n,L,U;
double ans;

int size[N],sum,mi,rt;
bool vis[N],b[N];

int head[N],tot;
struct aa
{
	int to,pre,dis;
}edge[N*2];
void addedge(int u,int v,int d)
{
	edge[++tot].to=v;edge[tot].pre=head[u];edge[tot].dis=d;head[u]=tot;
}

void get_size(int u,int fa)
{
	size[u]=1;b[u]=false;
	for (int i=head[u];i;i=edge[i].pre)
	if (!vis[edge[i].to]&&edge[i].to!=fa) 
	{
		get_size(edge[i].to,u);
		size[u]+=size[edge[i].to];
	}
}
void get_rt(int u,int fa)
{
	int mx=sum-size[u];
	for (int i=head[u];i;i=edge[i].pre)
	if (!vis[edge[i].to]&&edge[i].to!=fa)
	{
		get_rt(edge[i].to,u);
		mx=max(mx,size[edge[i].to]);
	}
	if (mx<mi) mi=mx,rt=u;
}



double f[N],g[N];
int q[N],tail,yy[N];

void bfs(int u,double d,double jian)
{
	int hd=1;tail=0;
	q[++tail]=u;yy[tail]=1,g[tail]=d;b[u]=true;
	while (hd<=tail)
	{
		int v=q[hd];
		for (int i=head[v];i;i=edge[i].pre)
		if (!vis[edge[i].to]&&!b[edge[i].to]) 
		{
			b[edge[i].to]=true;
			q[++tail]=edge[i].to;
			yy[tail]=yy[hd]+1;
			g[tail]=g[hd]+(double)edge[i].dis-jian;
		}
		hd++;
	} 
}

int q0[N],tl,hd;
double q1[N];
void push(int i)
{
	while (hd<=tl&&f[i]>q1[tl]) tl--;
	q0[++tl]=i,q1[tl]=f[i]; 
}

bool pan(double jian,int u)
{
	int mx=0;
	for (int ii=head[u];ii;ii=edge[ii].pre)
	if (!vis[edge[ii].to])
	{
		int v=edge[ii].to;
		bfs(v,(double)edge[ii].dis-jian,jian);
		
		hd=1,tl=1;q0[tl]=mx,q1[tl]=f[mx];
		 
		for (int i=1;i<=tail;i++)
		{
			int d=yy[i];double dis=g[i];
			int ll=max(L-d,0),rr=U-d;
			if (ll>mx) continue;
			if (rr<0) break;
			
			while (ll<q0[tl]) push(q0[tl]-1);
			while (rr<q0[hd]&&hd<=tl) hd++; 
			
			if (g[i]+q1[hd]>=0) 
			{
				for (int j=1;j<=mx;j++) f[j]=-1e11;
				for (int j=1;j<=tail;j++) b[q[j]]=false;
				return true;
			}
		}
		mx=max(mx,yy[tail]);
		mx=min(mx,U);
		for (int i=1;i<=tail;i++) 
		{
			int d=yy[i];double dis=g[i];b[q[i]]=false;
			if (d>U) continue;
			f[d]=max(f[d],dis);
		}
	}
	for (int i=1;i<=mx;i++) f[i]=-1e11;
	return false;
}


int lim;

void work(int u)
{
	double l=0,r=lim,mid;
	while (l+0.0001<r)
	{
		mid=(l+r)/2;
		if (pan(mid,u)) l=mid;
		else r=mid;
	}
//	printf("%lf\n",l);
	if (l>ans) ans=l;
}

void dfs(int u)
{
	get_size(u,0);sum=size[u];mi=inf;
	get_rt(u,0);u=rt;
	if (sum<=L) return ;
	vis[u]=true;
	work(u);
	
	for (int i=head[u];i;i=edge[i].pre)
	if (!vis[edge[i].to]) dfs(edge[i].to);
}

inline int read()
{
	int ans,f=1;char ch;
	while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
	while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
	return ans*f;
}

int main()
{
	n=read();L=read();U=read();
	int x,y,z;
	for (int i=1;i<n;i++)
	{
		x=read();y=read();z=read();
		addedge(x,y,z);
		addedge(y,x,z);
		lim=max(lim,z);
	}
	for (int i=1;i<=U;i++) f[i]=-1e11;
	dfs(1);
	printf("%.3f",ans);
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值