背景:
物理竞赛强势看错
∞
∞
∞道题。
这么水的题目,可是还是太粗心了(毒奶一口,没奖)。
要被班主任骂死了。
数理化信竞赛均爆炸(不过也不重要了)。
点分治套路:
[
1
]
.
[1].
[1].收集所有儿子的信息,然后一次性合并,并排除不合法的情况。
[
2
]
.
[2].
[2].顺次处理儿子的信息,处理一个合并一个。
题目传送门:
https://www.luogu.org/problemnew/show/P4149
题意:
一棵树,选出尽量少的边使全值和为
m
m
m。
思路:
就是顺次处理儿子的信息,处理一个合并一个。最后删去不合法的。
用一个
d
p
dp
dp来统计答案即可。
卡常(我的做法不够优秀)。
代码( 90 p t s 90pts 90pts,卡常):
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF int(1e8)
#define R register
#define I inline
using namespace std;
int n,m,len=0,ans;
int last[1000010],size[1000010],msize[1000010],dis[1000010],sum[1000010],d[1000010],f[1000010];
bool bz[1000010];
struct node{int x,y,z,next;} a[1000010];
int SIZE,MIN,ROOT,tot;
I int read()
{
int x=0,f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())
if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';x=(x<<3)+(x<<1)+(ch^48),ch=getchar());
return x*f;
}
void ins(int x,int y,int z)
{
a[++len]=(node){x,y,z,last[x]}; last[x]=len;
}
void find_root(int x,int fa)
{
size[x]=1;
msize[x]=0;
for(R int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa||bz[y]) continue;
find_root(y,x);
size[x]+=size[y];
msize[x]=max(msize[x],size[y]);
}
msize[x]=max(msize[x],SIZE-size[x]);
if(MIN>msize[x]) MIN=msize[x],ROOT=x;
}
void get_dis(int x,int fa)
{
if(dis[x]<=m) ans=min(ans,d[x]+f[m-dis[x]]);
for(R int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa||bz[y]) continue;
d[y]=d[x]+1;
dis[y]=dis[x]+a[i].z;
get_dis(y,x);
}
}
void update(int x,int fa,bool op)
{
if(dis[x]<=m)
{
if(op) f[dis[x]]=min(f[dis[x]],d[x]); else f[dis[x]]=INF;
}
for(R int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(bz[y]||y==fa) continue;
update(y,x,op);
}
}
void dfs(int x)
{
bz[x]=true;
f[0]=0;
for(R int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(bz[y]) continue;
d[y]=1;
dis[y]=a[i].z;
get_dis(y,0);
update(y,0,1);
}
for(R int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(bz[y]) continue;
update(y,0,0);
}
for(R int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(bz[y]) continue;
SIZE=size[y],MIN=n,ROOT=0;
find_root(y,0);
dfs(ROOT);
}
}
int main()
{
int x,y,z;
n=read(),m=read();
for(R int i=1;i<n;i++)
{
x++,y++;
x=read(),y=read(),z=read();
ins(x,y,z),ins(y,x,z);
}
ans=n;
for(R int i=0;i<=m;i++)
f[i]=INF;
SIZE=n,MIN=n,ROOT=0;
find_root(1,0);
dfs(ROOT);
printf("%d",ans==n?-1:ans);
}