• 题解-八省联考2018 林克卡特树


    我们先来转换一下题意,即为选 (k+1) 条互不相交的链,使得权值和最大。估计没人和我一样选 (k) 条小于 (0) 的边变成 (0)

    这个东西看起来就只能 dp 求,设 f[i,j,0/1/2] 代表以 i 为根的子树选出 j 条链,然后 i 不选,i 是一条链的顶,i 的子树中有一条穿过 i 的链。

    然后转移就比较显然了,为了方便,我们最后合并信息到 (f[i,j,0]) 上。通过打表我们发现这是一个关于 j 的凸函数,所以可以 wqs 二分。根据数据范围也可以猜测。我们稍微改写一下 dp 方程即可。

    然后我的写法又丑又难写还难调,于是我打开了题解,看到了下面这种写法,稍微学习了一下(就是用一个 pair 来存,然后重载运算符)。

    #include<bits/stdc++.h>
    #define pi pair<ll,int>
    #define mp make_pair
    #define fi first
    #define se second
    typedef long long ll;
    using namespace std;
    const int maxn=600005;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    template<typename T>
    void read(T &x){
    	T flag=1;
    	char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())if(ch=='-')flag=-1;
    	for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    	x*=flag;
    }
    int n,m;
    int pre[maxn],to[maxn],val[maxn],head[maxn],tot=1;
    pi f[maxn][3],I;
    pi operator+(pi a,pi b){
    	return mp(a.fi+b.fi,a.se+b.se);
    }
    pi operator+(pi a,ll b){
    	return mp(a.fi+b,a.se);
    }
    bool operator<(pi a,pi b){
    	if(a.fi!=b.fi)return a.fi<b.fi;
    	return a.se<b.se;
    }
    void add_edge(int u,int v,int w){
    	pre[++tot]=head[u];to[tot]=v;val[tot]=w;head[u]=tot;
    }
    void dfs(int u,int fa){
    	f[u][0]=f[u][1]=f[u][2]=mp(0,0);
    	f[u][2]=max(f[u][2],I);
    	for(int i=head[u];i;i=pre[i]){
    		int v=to[i];
    		if(v==fa)continue;
    		dfs(v,u);
    		f[u][2]=max(f[u][2],max(f[u][2]+f[v][0],f[u][1]+f[v][1]+I+val[i]));
    		f[u][1]=max(f[u][1],max(f[u][0]+f[v][1]+val[i],f[u][1]+f[v][0]));
    		f[u][0]=max(f[u][0],f[u][0]+f[v][0]);
    	}
    	f[u][0]=max(f[u][0],max(f[u][1]+I,f[u][2]));
    }
    int main(){
    	read(n);read(m);m++;
    	for(int i=1,u,v,w;i<n;i++){
    		read(u);read(v);read(w);
    		add_edge(u,v,w);add_edge(v,u,w);
    	}
    	ll l=-1e12,r=1e12,res=0;
    	while(l<=r){
    		ll mid=(l+r)/2;
    		I=mp(-mid,1);
    		dfs(1,0);
    		int v=f[1][0].se;
    		if(v>=m){
    			res=mid;
    			l=mid+1;
    		}else{
    			r=mid-1;
    		}
    	}
    	I=mp(-res,1);
    	dfs(1,0);
    	printf("%lld
    ",f[1][0].fi+res*m);
    	return 0;
    }
    
  • 相关阅读:
    【NOIP16提高组】换教室
    【扬中集训Day6T1】 白日梦
    【POJ 1061】 青蛙的约会
    【扬中集训DAY5T1】 交换矩阵
    【USACO】 Balanced Photo
    【USACO】 Balanced Lineup

    POJ P3352 Road Construction 解题报告
    洛谷 P2783 有机化学之神偶尔会做作弊 解题报告
    洛谷 P2300 合并神犇 解题报告
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/15045699.html
Copyright © 2020-2023  润新知