P4383 [八省联考2018]林克卡特树
题目
分析
首先这个题需要转化。
发现对于删掉的每一条边,如果我们不走这个子树,那么其实删掉是毫无意义的,所以我们可以假设我们一定会走所有“割”下来的子树,那么其实我们可以更近一步,一定会走“割”下来的一条链?
然后因为这里可以剩下的部分不用割掉,所以我们可以考虑这样转化(这里只是略解,感性理解,实际可以去看看题解):求树上选择 \(k\) 条不交的链的权值之和的最大值。
发现这个可以dp,具体过程不再赘述。
然后我们闲来无事打了个表(\(k=1,2,3...\))发现这东西具有单调性(?)(似乎没有人给出证明)
于是可以考虑wqs二分,那么复杂度变成 \(O(n\log{V})\) ,可以通过。
代码
#include<bits/stdc++.h>
using namespace std;
//#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define ll long long
const int N=3e5+5;
const ll INF=1e12;
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int n,m;
ll l=-INF,r=INF,mid,ans=-1;
struct node{
ll x,y;
node(ll x=0,ll y=0):x(x),y(y){}
inline bool operator < (const node &B)const{return x==B.x?y>B.y:x<B.x;}
inline node operator + (const node &B)const{return node(x+B.x,y+B.y);}
inline node operator + (const ll &B)const{return node(x+B,y);}
}dp[N][3];
int head[N],to[N<<1],nex[N<<1],val[N<<1],idx;
inline node ad(node x){return node(x.x-mid,x.y+1);}
inline void add(int u,int v,int w){nex[++idx]=head[u];to[idx]=v;val[idx]=w;head[u]=idx;return ;}
void dfs(int u,int fa){
dp[u][2]=max(dp[u][2],node{-mid,1});
for(int i=head[u];i;i=nex[i]){
int v=to[i];
if(v==fa) continue;
dfs(v,u);
dp[u][2]=max(dp[u][2]+dp[v][0],ad(dp[u][1]+dp[v][1]+val[i]));
dp[u][1]=max(dp[u][1]+dp[v][0],dp[u][0]+dp[v][1]+val[i]);
dp[u][0]=dp[u][0]+dp[v][0];
}
dp[u][0]=max(dp[u][0],max(ad(dp[u][1]),dp[u][2]));
}
signed main(){
read(n),read(m);m++;
ll T=0;
for(int i=1;i<n;i++){
int u,v,w;
read(u),read(v),read(w);
add(u,v,w),add(v,u,w);T+=abs(w);
}
l=-T,r=T;
while(l<=r){
mid=l+r>>1;
memset(dp,0,sizeof(dp));
dfs(1,0);
if(dp[1][0].y<=m) r=mid-1;
else l=mid+1;
}
memset(dp,0,sizeof(dp));
mid=l;dfs(1,0);
write(dp[1][0].x+m*l);
return 0;
}