zoukankan      html  css  js  c++  java
  • 【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
    ");
    	else
    		printf("%d
    ",ans);
    }
    
  • 相关阅读:
    PAT (Basic Level) Practise 1013 数素数
    PAT (Basic Level) Practise 1014 福尔摩斯的约会
    codeforces 814B.An express train to reveries 解题报告
    KMP算法
    rsync工具
    codeforces 777C.Alyona and Spreadsheet 解题报告
    codeforces 798C.Mike and gcd problem 解题报告
    nginx + tomcat多实例
    MongoDB副本集
    指针的艺术(转载)
  • 原文地址:https://www.cnblogs.com/chen1352/p/9045313.html
Copyright © 2011-2022 走看看