zoukankan      html  css  js  c++  java
  • P3574 [POI2014]FAR-FarmCraft 树上DP

    题意:

    给定一棵大小为(n)树,走过每条边需要花费(1)时间,安装软件又需要花费(c_i)时间,需要遍历整棵树并回到起点,想让所有点中到达时间+安装时间的最大值最小,问这个值是多少

    范围&性质:(1le nle 5 imes10^5,1le c_ile 10^9)

    分析:

    我们对于节点(u)的儿子,按照最优方案下安装时间排序,我们二分一个最优时间,对于这些点我们从大往小的加入队列中,若当前的点无法直接插入到队列末尾,那就将他插入到最后一个元素的前面,这样能保证他影响到的点最少,要注意最后将(1)点得到的方案,和(c_1+(n-1)*2)取一次(max)

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
    	const int maxn = 5e5+5;
    	const long long inf = 1e15+5; 
    	long long f[maxn],head[maxn],siz[maxn],c[maxn];
        int n,cnt=0,tot;
    	
    	struct edge
    	{
    		int to,nxt;
    	}e[maxn<<1];
    	
    	struct node
    	{
    		int f,t;
    		bool operator<(const node &b)const
    		{
    			return f>b.f;
    		}
    	}p[maxn]; 
    	
    	void add(int u,int v)
    	{
    		e[++cnt].to=v;
    		e[cnt].nxt=head[u];
    		head[u]=cnt;
    	}
    	
    	bool check(long long x)
    	{
    		int i,ed=0;
    		long long last=0;
    		for(int i=1;i<=tot;i++)
    		{
    			if(last+p[i].f<=x) last+=p[i].t,ed=i;
    			else if(last-p[ed].t+p[i].t+p[ed].f>x) return false;
    			else last+=p[i].t;
    		}
    		return true;
    	}
    	
    	void dfs(int u,int fa)
    	{
    		siz[u]=1;
    		for(int i=head[u];i;i=e[i].nxt)
    		{
    			int v=e[i].to;
    			if(v==fa) continue;
    			dfs(v,u);
    			siz[u]+=siz[v];
    		}
    		tot=0;
    		for(int i=head[u];i;i=e[i].nxt)
    		{
    			int v=e[i].to;
    			if(v==fa) continue;
    			p[++tot].f=f[v];
    			p[tot].t=siz[v]*2ll;
    		}
    		sort(p+1,p+tot+1);
    		long long l=p[1].f,r=inf,mid;
    		while(l<r)
    		{
    			mid=(l+r)>>1;
    			if(check(mid)) r=mid;
    			else l=mid+1;
    		}
    		if(fa) f[u]=c[u];
    		else f[u]=c[u]+((n-1)<<1);
    		if(tot&&f[u]<l+1) f[u]=l+1;
    	}
    	
    	void work()
    	{
    		int a,b;
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++) scanf("%lld",&c[i]);
    		for(int i=1;i<n;i++)
    		{
    			scanf("%d%d",&a,&b);
    			add(a,b);add(b,a);
    		}
    		dfs(1,0);
    		printf("%lld
    ",f[1]);
    	}
    	
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
  • 相关阅读:
    鼠标事件:
    各种坑记录
    Go学习笔记
    Scala学习笔记-7-代码片段
    Go学习笔记
    NIO学习笔记
    Redis常用操作
    docker & k8s 笔记
    Node常用笔记
    Maven常用笔记
  • 原文地址:https://www.cnblogs.com/youth518/p/13716080.html
Copyright © 2011-2022 走看看