给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小.
给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小.
第一行 两个整数 n, k
第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)
一个整数 表示最小边数量 如果不存在这样的路径 输出-1
树的点分治
t[i]表示长度为i的路径最少有多少条边,分治的同时更新t数组和计算答案。注意这里要一边更新t数组一边计算答案。
每次初始化不能用memset,否则会TLE,可以按照DFS的顺序依次将更新的值恢复原值。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define ll long long #define maxn 200005 #define inf 1000000000 using namespace std; int n,k,cnt,root,ans; int head[maxn],sz[maxn],mx[maxn],dep[maxn],dis[maxn],t[1000005]; bool vst[maxn]; struct edge_type{int next,to,v;}e[maxn*2]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void add_edge(int x,int y,int z) { e[++cnt]=(edge_type){head[x],y,z};head[x]=cnt; e[++cnt]=(edge_type){head[y],x,z};head[y]=cnt; } inline void dfssize(int x,int fa) { sz[x]=1;mx[x]=0; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (!vst[y]&&y!=fa) { dfssize(y,x); sz[x]+=sz[y]; mx[x]=max(mx[x],sz[y]); } } } inline void dfsroot(int rt,int x,int fa) { mx[x]=max(mx[x],sz[rt]-sz[x]); if (mx[x]<mx[root]) root=x; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (!vst[y]&&y!=fa) dfsroot(rt,y,x); } } inline void calc(int x,int fa) { if (dis[x]<=k) ans=min(ans,dep[x]+t[k-dis[x]]); for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (!vst[y]&&y!=fa) { dep[y]=dep[x]+1;dis[y]=dis[x]+e[i].v; calc(y,x); } } } inline void add(int x,int fa,int flag) { if (dis[x]<=k) { if (flag) t[dis[x]]=min(t[dis[x]],dep[x]); else t[dis[x]]=inf; } for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (!vst[y]&&y!=fa) add(y,x,flag); } } inline void solve(int x) { root=0; dfssize(x,0); dfsroot(x,x,0); vst[root]=true;t[0]=0; for(int i=head[root];i;i=e[i].next) { int y=e[i].to; if (!vst[y]) { dep[y]=1;dis[y]=e[i].v; calc(y,0); add(y,0,1); } } for(int i=head[root];i;i=e[i].next) { int y=e[i].to; if (!vst[y]) add(y,0,0); } for(int i=head[root];i;i=e[i].next) { int y=e[i].to; if (!vst[y]) solve(y); } } int main() { n=read();k=read(); F(i,1,n-1) { int x=read()+1,y=read()+1,z=read(); add_edge(x,y,z); } F(i,1,k) t[i]=n; ans=mx[0]=n; solve(1); if (ans!=n) printf("%d\n",ans); else puts("-1"); return 0; }