题目
输入样例#1:
4 3
0 1 1
1 2 2
1 3 4
输出样例#1:
2
n≤200000,K≤1000000
日你????啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
可以use[d[l].dep+d[r].dep]+=f。按照正常的点分治来。。我他妈一直WA啊啊啊。
一定要调出来,这也太难受了。。。但是尺取的时候 复杂度可能会达到很高。。
不这样的话可以 子树一个一个的计算。不是像以前一样getd()的到一大堆再减去子树内部不合法的情况。一个一个的计算时,先计算完毕后,再把计算的这个子树更新进去,就不会发生重复了。然后一个树算完之后,把这个树都清空。清空操作和更新操作可以用一个函数,memset的话也许会T。
到底如何计算呢:每次计算子树x之前,前x-1颗的子树t[i]值会被更新好,t[i]代表dis是i时的最少边;
cal(): ans=min(ans,t[K-dis[x]+dep[x])。
modify: t[dis[x]]=min(t[dis[x]],dep[x]);
日你????啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#define foru(i,a,b) for(int i=a;i<=b;++i)
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int N=2e5+5,M=1e6+5,INF=0x3f3f3f3f;
template<class T>void rd(T &x)
{
x=0;int f=0;char ch=getchar();
while(ch<'0'||ch>'9') {f|=(ch=='-');ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return;
}
struct Edge{int to,len,nex;}edge[N<<1];
int head[N],tot;
void add(int from,int to,int len)
{
edge[++tot]=(Edge){to,len,head[from]};head[from]=tot;
edge[++tot]=(Edge){from,len,head[to]};head[to]=tot;
}
int sum,root,ans;
int sz[N],mx[N],vis[N];
void getroot(int x,int fa)
{
sz[x]=1,mx[x]=0;
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to;
if(vis[y]||y==fa) continue;
getroot(y,x);
sz[x]+=sz[y];
mx[x]=max(mx[x],sz[y]);
}
mx[x]=max(mx[x],sum-sz[x]);
if(mx[x]<mx[root]) root=x;
}
int dis[N],dep[N];
int t[M],K;//t[i]表示前面有个点已经走了距离i的最小边数.
void cal(int x,int fa)
{
if(dis[x]<=K)
ans=min(ans,t[K-dis[x]]+dep[x]);
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to;
if(vis[y]||y==fa) continue;
dep[y]=dep[x]+1,dis[y]=dis[x]+edge[i].len;
cal(y,x);
}
}
void modify(int x,int fa,int f)
{
if(dis[x]<=K)
{
if(f==1) t[dis[x]]=min(t[dis[x]],dep[x]);
else t[dis[x]]=INF;
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to;
if(vis[y]||y==fa) continue;
modify(y,x,f);
}
}
}
void work(int x)
{
vis[x]=1;
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to;
if(vis[y]) continue;
dep[y]=1,dis[y]=edge[i].len;
cal(y,x);
modify(y,x,1);
}
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to;
if(vis[y]) continue;
modify(y,x,-1);
}
sum=sz[x],root=0;
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to;
if(vis[y]) continue;
sum=sz[y],root=0;
getroot(y,x);
work(root);
}
}
int main()
{
int n;rd(n),rd(K);
foru(i,1,K) t[i]=INF;
foru(i,1,n-1)
{
int u,v,w;rd(u),rd(v),rd(w);
++u,++v;
add(u,v,w);
}
sum=n,root=0,mx[0]=INF,ans=INF;
getroot(1,-1);
work(root);
printf("%d\n",ans==INF?-1:ans);
}