题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2599
题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小.
题意:每次找到当前树的重心作为树根,查找通过当前树根的路径。
struct node
{
int v,w;
node(){}
node(int _v,int _w)
{
v=_v;
w=_w;
}
};
vector<node> g[N];
int n,m;
int dis[N*5],cnt[N*5],h[N*5];
int visit[N];
int ans;
int f[N],s[N];
vector<int> V;
void dfs(int u,int pre)
{
V.pb(u); s[u]=1;
int i,v,Max=0;
FOR0(i,SZ(g[u]))
{
v=g[u][i].v;
if(visit[v]||v==pre) continue;
dfs(v,u);
s[u]+=s[v];
upMax(Max,s[v]);
}
f[u]=Max;
}
int getRoot(int u)
{
V.clear();
dfs(u,-1);
int Min=n,ans=u,i,temp;
FOR0(i,SZ(V))
{
u=V[i];
temp=max(f[u],(int)SZ(V)-f[u]);
if(temp<Min) Min=temp,ans=u;
}
return ans;
}
int d[N],K,a[N*5];
void dfs1(int u,int pre)
{
if(dis[u]>m) return;
if(h[m-dis[u]]==K) upMin(ans,a[m-dis[u]]+cnt[u]);
int i,v,w;
FOR0(i,SZ(g[u]))
{
v=g[u][i].v;
w=g[u][i].w;
if(v==pre||visit[v]) continue;
dis[v]=dis[u]+w;
cnt[v]=cnt[u]+1;
dfs1(v,u);
}
}
void dfs2(int u,int pre)
{
if(dis[u]>m) return;
if(h[dis[u]]!=K) a[dis[u]]=cnt[u],h[dis[u]]=K;
else upMin(a[dis[u]],cnt[u]);
int i,v;
FOR0(i,SZ(g[u]))
{
v=g[u][i].v;
if(v==pre||visit[v]) continue;
dfs2(v,u);
}
}
void DFS(int u)
{
u=getRoot(u); h[0]=++K;
int i,v,w;
FOR0(i,SZ(g[u]))
{
v=g[u][i].v;
w=g[u][i].w;
if(visit[v]) continue;
dis[v]=w;
cnt[v]=1;
dfs1(v,u);
dfs2(v,u);
}
visit[u]=1;
FOR0(i,SZ(g[u]))
{
v=g[u][i].v;
if(visit[v]) continue;
DFS(v);
}
}
int main()
{
RD(n,m);
int i,x,y,w;
FOR1(i,n-1)
{
RD(x,y,w);
g[x].pb(node(y,w));
g[y].pb(node(x,w));
}
ans=n; DFS(0);
if(ans==n) ans=-1;
PR(ans);
}