歌名 - 歌手
0:00

    【NOIP2016提高A组模拟8.19】(雅礼联考day2)树上路径

    题目

    给出一棵树,求出最小的k,使得,且在树中存在路径p,使得k>=S且k<=E。(k为路径p上的边的权值和)。

    分析

    点分治,设当前为x的,求在以x为根的子树中,经过x的路径(包括起点或终点在x)中长度大于等于S的最小值。
    假设i有3个儿子,j、k、l,
    首先将以j为根的子树中的所有点到x的距离求出来,放进队列中。排个序。
    接着将以k为根的子树中的所有点到x的距离求出来,一个一个点枚举,在队列中二分,求出一段大于等于S并且最小的路径,与ans比较,取小。再将它们放进队列中。排个序。
    再以j为根的子树中的所有点到x的距离求出来,同样更新答案,在再加入队列。
    对于起点或终点在x的,在一开始就加入队列,就可以了。
    时间复杂度\(O(nlog_2^2n)\)
    事实上菊花图卡不过,但还是水过了。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const int N=100005;
    using namespace std;
    int dis[N],d[N],root,last[N],next[N*2],to[N*2],v[N*2],s,e,ans=maxlongint,n,m,tot,size[N],mx,ff;
    bool bz[N];
    int bj(int x,int y,int z)
    {
    	next[++tot]=last[x];
    	last[x]=tot;
    	to[tot]=y;
    	v[tot]=z;
    }
    int findroot(int x,int fa)
    {
    	size[x]=1;
    	int num=0;
    	for(int i=last[x];i;i=next[i])
    	{
    		int j=to[i];
    		if(j!=fa && bz[j])
    		{
    			findroot(j,x);
    			size[x]+=size[j];
    			num=max(num,size[j]);
    		}
    	}
    	num=max(ff-size[x],num);
    	if(num<mx)
    	{
    		root=x;
    		mx=num;
    	} 
    }
    int sodis(int x,int fa,int val)
    {
    	d[++tot]=val;
    	for(int i=last[x];i;i=next[i])
    	{
    		int j=to[i];
    		if(j!=fa && bz[j])
    		{
    			sodis(j,x,val+v[i]);
    		}
    	}
    }
    int rf(int l,int r,int val)
    {
    	while(l<r)
    	{
    		int mid=(l+r)/2;
    		if(d[mid]+val<s)
    			l=mid+1;
    		else
    			r=mid;
    	}
    	if(d[l]+val>=s)
    		ans=min(d[l]+val,ans);
    	else
    	if(d[r]+val>=s)
    		ans=min(d[r]+val,ans);
    }
    int dg(int x,int fa)
    {
    	bz[x]=false;
    	tot=1;
    	d[1]=0;
    	for(int i=last[x];i;i=next[i])
    	{
    		int j=to[i];
    		if(j!=fa && bz[j])
    		{
    			int k=tot+1;
    			sodis(j,x,v[i]);
    			for(int l=k;l<=tot;l++)
    			{
    				rf(1,k-1,d[l]);
    			}
    			sort(d+1,d+1+tot);
    		}
    	}
    	int f=tot;
    	for(int i=last[x];i;i=next[i])
    	{
    		int j=to[i];
    		if(j!=fa && bz[j])
    		{
    			ff=f-1;
    			root=0;
    			mx=maxlongint;
    			findroot(j,x);
    			dg(root,x);
    		}
    	}
    }
    int main()
    {
    	scanf("%d%d%d",&n,&s,&e);
    	for(int i=1;i<=n-1;i++)
    	{
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		bj(x,y,z);
    		bj(y,x,z);
    	}
    	memset(bz,true,sizeof(bz));
    	root=0;
    	ff=n;
    	mx=maxlongint;
    	findroot(1,0);
    	dg(root,0);
    	if(ans>e)
    		printf("-1\n");
    	else
    		printf("%d\n",ans);
    }
    
    posted @ 2018-05-16 12:16  无尽的蓝黄  阅读(207)  评论(0编辑  收藏  举报