题目描述
给一棵树,每条边有权。求一条简单路径,权值和等于 K K K,且边的数量最小。
输入格式:
第一行:两个整数
n
,
k
n,k
n,k
第二至
n
n
n 行:每行三个整数,表示一条无向边的两端和权值 (注意点的编号从
0
0
0 开始)。
输出格式:
一个整数,表示最小边数量。
如果不存在这样的路径,输出
−
1
−1
−1。
说明
n ≤ 200000 , K ≤ 1000000 n\le 200000,K\le 1000000 n≤200000,K≤1000000
题目分析
很裸的点分啊,当复习好了
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return x*f;
}
const int maxn=200010,inf=1128481603;
int n,k;
struct node{int v,dis,nxt;}E[maxn<<1];
int head[maxn],tot;
int maxp[maxn],size[maxn],vis[maxn],sum,rt;
int dis[maxn],rem[maxn],num[maxn];
int judge[maxn*5],q[maxn],ans=inf;
void add(int u,int v,int dis)
{
E[++tot].nxt=head[u];
E[tot].v=v; E[tot].dis=dis;
head[u]=tot;
}
void getrt(int u,int pa)
{
size[u]=1; maxp[u]=0;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(v==pa||vis[v]) continue;
getrt(v,u);
size[u]+=size[v];
maxp[u]=max(maxp[u],size[v]);
}
maxp[u]=max(maxp[u],sum-size[u]);
if(maxp[u]<maxp[rt]) rt=u;
}
void getdis(int u,int pa,int cnt)
{
if(dis[u]>k) return; //num记录边数
ans=min(ans,judge[k-dis[u]]+cnt);
rem[++rem[0]]=dis[u]; num[rem[0]]=cnt;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(v==pa||vis[v]) continue;
dis[v]=dis[u]+E[i].dis;
getdis(v,u,cnt+1);
}
}
void calc(int u)
{
int p=0;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(vis[v]) continue;
rem[0]=0; dis[v]=E[i].dis;
getdis(v,u,1);
for(int j=1;j<=rem[0];++j)
q[++p]=rem[j],judge[rem[j]]=min(judge[rem[j]],num[j]);
}
for(int i=1;i<=p;++i)
judge[q[i]]=inf;
}
void solve(int u)
{
vis[u]=1; judge[0]=0; calc(u);
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(vis[v])continue;
sum=size[v]; maxp[rt=0]=inf;
getrt(v,0); solve(rt);
}
}
int main()
{
n=read();k=read();
for(int i=1;i<n;++i)
{
int u=read()+1,v=read()+1,dis=read();
add(u,v,dis); add(v,u,dis);
}
memset(judge,67,sizeof(judge));
maxp[rt]=sum=n; getrt(1,0);
solve(rt);
if(ans==inf) printf("-1\n");
else printf("%d\n",ans);
return 0;
}