zoukankan      html  css  js  c++  java
  • [八省联考2018]林克卡特树lct

    题面在这里

    description

    一个(N)个点的(Tree),每条边有一个整数边权(v_i),表示走这条边会获得(v_i)的收益;
    (L)需要控制主角(Link),(Cut)掉树上的恰好(K)条边,然后再连接(K)条边权为$ 0(的边,得到一棵新的树。 接着,他会选择树上的两个点)p,q,(并沿着树上连接这两点的简单路径从)p(走到)q(,并为经过的每条边获取相应收益。 请求出)Link$能得到的最大总收益。

    data range

    对于(10%)的数据,(k = 0);
    对于另外(10%)的数据,(k = 1);
    对于另外(15%)的数据,(k = 2);
    对于另外(25%)的数据,(k le 100);
    对于全部的测试数据,
    保证有(1le Nle 3 imes 10^5,1 le x_i, y_i le N; |v_i| le 10^6)

    Hint

    题目并不难。

    solution

    上面的提示并不能让我这种蒟蒻得到什么有用的信息

    不过分析一波之后还是能发现题意求的是树上(k)条点不相交直径的最大边权和

    60 point

    使用树形DP就好啦
    (f[x][k][d=0,1,2])表示在(x)的子树中选取(k)调不相交的链,
    (x)的度数为(d)时的最大链长和
    合并的时候需要注意讨论一下,由于不是重点所以没有写得那么详细,
    具体实现请看代码

    100 point

    当树的形态一定时,选取(k)条链时的最优解(best_k)是上凸的
    真是神一般的性质啊

    于是我们想到用直线去切这个凸包
    那么用一条斜率为(k)的直线切这个凸包(best_x)的意义是什么呢?
    本蒟蒻是这么理解的(图画得不好,看看就行了):
    此处输入图片的描述
    当我们要用一条直线(y=kx)切凸包的时候,这个切点满足(best_x-kx)最大。
    那么我们可以转而在树上选任意条数的链,但每条链需要花费(k)的代价,
    之后树形DP求出满足这个条件的链条数和代价(这是可以(O(n))做的),
    就是我们直线要切的点((x,best_x-kx))

    二分斜率,于是我们就做完了这道题?
    复杂度为(O(nlog(sum w)))

    code

    这里是60分的DP(未经在线测试)

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define FILE "lct"
    #define RG register
    #define il inline
    using namespace std;
    typedef long long ll;
    typedef double dd;
    typedef vector<int> VI;
    const int N=300010;
    const ll INF=1e18;
    il ll read(){
    	RG ll d=0,w=1;char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')d=d*10+ch-48,ch=getchar();
    	return d*w;
    }
    
    il void file(){
    	freopen(FILE".in","r",stdin);
    	freopen(FILE".out","w",stdout);
    }
    
    int n,k;
    int head[N],nxt[N<<1],to[N<<1],val[N<<1],cnt;
    il void add(int u,int v,int w){
    	to[++cnt]=v;
    	nxt[cnt]=head[u];
    	val[cnt]=w;
    	head[u]=cnt;
    }
    
    ll f[N][105][3],ans;
    il void update(ll &a,ll b){a=a>b?a:b;}
    #define fs (max(f[son][j][0],max(f[son][j][3],f[son][j][2])))
    il void DP(int son,int fa,int e){
    	for(RG int i=k;i;i--)
    		for(RG int j=0;i-j+1>=0;j++){
    			update(f[fa][i][2],f[fa][i-j+1][4]+f[son][j][5]+val[e]);
    			if(i-j>=0)update(f[fa][i][2],f[fa][i-j][2]+fs);			
    		}
    	
    	for(RG int i=k;i;i--)
    		for(RG int j=0;i-j>=0;j++){
    			if(i-j-1>=0)
    				update(f[fa][i][6],f[fa][i-j-1][0]+f[son][j][0]);
    			update(f[fa][i][7],f[fa][i-j][0]+f[son][j][8]+val[e]);
    			update(f[fa][i][9],f[fa][i-j][10]+fs);
    		}
    	
    	for(RG int i=k;i;i--)
    		for(RG int j=0;i-j>=0;j++)
    			update(f[fa][i][0],f[fa][i-j][0]+fs);
    }
    
    void dfs(int u,int fa){
    	f[u][0][0]=f[u][11][1]=0;
    	for(RG int i=head[u];i;i=nxt[i]){
    		RG int v=to[i];if(v==fa)continue;
    		dfs(v,u);DP(v,u,i);
    	}
    }
    
    int main()
    {
    	n=read();k=read()+1;
    	for(RG int i=1,u,v,w;i<n;i++){
    		u=read();v=read();w=read();
    		add(u,v,w);add(v,u,w);
    	}
    	memset(f,-127/3,sizeof(f));
    	dfs(1,0);
    	
    	for(RG int i=1;i<=n;i++)
    		ans=max(max(ans,f[i][k][0]),max(f[i][k][12],f[i][k][2]));
    	
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    这里是AC代码,搞了个pair方便统计答案

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define FILE "lct"
    #define RG register
    #define il inline
    #define line first
    #define val second
    using namespace std;
    typedef long long ll;
    typedef double dd;
    typedef vector<int> VI;
    typedef pair<ll,ll> PL;
    const int N=300010;
    const ll INF=1e18;
    il ll read(){
    	RG ll d=0,w=1;char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')d=d*10+ch-48,ch=getchar();
    	return d*w;
    }
    
    il void file(){
    	freopen(FILE".in","r",stdin);
    	freopen(FILE".out","w",stdout);
    }
    
    int n,k;
    int head[N],nxt[N<<1],to[N<<1],val[N<<1],cnt;
    il void add(int u,int v,int w){
    	to[++cnt]=v;
    	nxt[cnt]=head[u];
    	val[cnt]=w;
    	head[u]=cnt;
    }
    
    PL f[N][3];
    PL operator +(PL a,PL b){
    	return (PL){a.line+b.line,a.val+b.val};
    }
    PL operator +(PL a,ll v){a.val+=v;return a;}
    il PL max(PL a,PL b){
    	if(a.val>b.val)return a;
    	else if(a.val==b.val&&a.line>b.line)return a;
    	return b;
    }
    il void update(PL &a,PL b,int l){b.line+=l;a=max(a,b);}
    #define fs (max(f[son][0],max(f[son][1],f[son][2])))
    il void DP(int son,int fa,int e,ll K){
    	update(f[fa][2],f[fa][2]+fs,0);
    	update(f[fa][2],f[fa][1]+f[son][1]+val[e]+K,-1);
    	
    	update(f[fa][1],f[fa][1]+fs,0);
    	update(f[fa][1],f[fa][0]+f[son][0]+(-K),1);
    	update(f[fa][1],f[fa][0]+f[son][1]+val[e],0);
    	
    	update(f[fa][0],f[fa][0]+fs,0);
    }
    void dfs(int u,int fa,ll K){
    	f[u][0]=(PL){0,0};f[u][1]=(PL){1,-K};
    	f[u][2]=(PL){0,-INF};
    	for(RG int i=head[u];i;i=nxt[i]){
    		RG int v=to[i];if(v==fa)continue;
    		dfs(v,u,K);DP(v,u,i,K);
    	}
    }
    
    PL work(ll K){
    	RG PL ans;ans=(PL){0,-INF};
    	dfs(1,0,K);
    	for(RG int i=1;i<=n;i++)
    		ans=max(max(ans,f[i][0]),max(f[i][1],f[i][2]));
    	return ans;
    }
    
    int main()
    {
    	n=read();k=read()+1;RG ll L=0,R=0,M;RG PL ret;
    	for(RG int i=1,u,v,w;i<n;i++){
    		u=read();v=read();w=read();
    		add(u,v,w);add(v,u,w);R+=abs(w);L-=abs(w);
    	}
    	
    	while(L<R){
    		M=(L+R)>>1;ret=work(M);
    		if(ret.line<=k)R=M;else L=M+1;
    	}
    	ret=work(R);
    	printf("%lld
    ",ret.val+ret.line*R);
    	return 0;
    }
    

    诸位珍重,望来日以富贵相见。

  • 相关阅读:
    Confluence 6 删除垃圾内容
    Confluence 6 在 Apache 或者系统级别阻止垃圾
    Confluence 6 避免和清理垃圾
    Confluence 6 配置 简易信息聚合(RSS)
    Confluence 6 匿名访问远程 API
    Confluence 6 使用电子邮件可见
    Confluence 6 配置 XSRF 保护
    Confluence 6 为登录失败编辑,禁用和配置验证码
    Confluence 6 为登录失败配置使用验证码
    Confluence 6 为搜索引擎隐藏外部链接
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8783115.html
Copyright © 2011-2022 走看看