Description
Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree……
于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的点有一个距离(什么是距离不用说吧),他需要对于每个点回答:从这个点出发的第k小距离是多少;
如果atm不能回答出来,那么明天4019的闹钟将不会响,4019全寝可能就迟到了,所以atm希望你帮帮他。
Input
第一行,两个正整数n,k,表示树的点数,询问的是第几小距离;
第二~n行,每行三个正整数x,y,w,表示x和y之间有一条边,x为父亲,边权为w;
Output
n行, 每行一个数,第i行输出从i开始第k小距离
Sample Input
5 2
1 5 2
1 2 4
2 3 6
2 4 5
Sample Output
4
5
10
9
6
HINT
100% n<=15000, 边权在1~10之间,为了方便,保证1为根;
Source
同BZOJ2051
发着烧我好痛苦T_T
文化课会让发烧更加严重所以来写点代码转移注意力以不那么难受
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define GET (ch>='0'&&ch<='9')
#define MAXN 15010
#define MAXM 500010
using namespace std;
int n,k,Size,top,Top,rt,cnt;
int size[MAXN],f[MAXN];
int q[MAXM<<1],tail;
int rl[MAXN],rr[MAXN],el[MAXN],er[MAXN];
void in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
struct edge
{
int to,w;
bool vis;
edge *next,*rev;
}e[MAXN<<1],*prev[MAXN];
struct Edge
{
int to[2],w;
bool vis;
Edge *next,*rev;
}E[MAXM<<1],*Prev[MAXM];
void insert(int u,int v,int w)
{
e[++top].to=v;e[top].w=w;e[top].next=prev[u];prev[u]=&e[top];
}
void Insert(int u,int v1,int v2,int w)
{
E[++Top].to[0]=v1;E[Top].to[1]=v2;E[Top].w=w;E[Top].next=Prev[u];Prev[u]=&E[Top];
}
void get_G(int x,int fa)
{
size[x]=1;f[x]=0;
for (edge *i=prev[x];i;i=i->next)
if (!i->vis&&i->to!=fa) get_G(i->to,x),size[x]+=size[i->to],f[x]=max(f[x],size[i->to]);
f[x]=max(f[x],Size-size[x]);
if (f[x]<f[rt]) rt=x;
}
void dfs(int x,int fa,int dis)
{
q[++tail]=dis;
for (edge *i=prev[x];i;i=i->next)
if (!i->vis&&i->to!=fa) dfs(i->to,x,dis+i->w);
}
void dfs2(int x,int fa,int dis)
{
Insert(x,rt,cnt,dis);q[++tail]=dis;
for (edge *i=prev[x];i;i=i->next)
if (!i->vis&&i->to!=fa) dfs2(i->to,x,dis+i->w);
}
void solve(int x)
{
rl[x]=++tail;q[tail]=0;
for (edge *i=prev[x];i;i=i->next)
if (!i->vis) dfs(i->to,x,i->w);
rr[x]=tail;sort(q+rl[x],q+rr[x]+1);
for (edge *i=prev[x];i;i=i->next)
if (!i->vis) el[++cnt]=tail+1,dfs2(i->to,x,i->w),er[cnt]=tail,sort(q+el[cnt],q+er[cnt]+1);
for (edge *i=prev[x];i;i=i->next)
if (!i->vis) i->rev->vis=1,f[0]=Size=size[i->to],rt=0,get_G(i->to,rt),solve(rt);
}
int Query(int L,int R,int val)
{
int l=L,r=R,mid=(l+r)>>1;R=l-1;
while (l<=r)
{
mid=(l+r)>>1;
if (q[mid]<=val) l=mid+1,R=mid;
else r=mid-1;
}
return R-L+1;
}
int check(int x,int val)
{
int ret=Query(rl[x],rr[x],val)-1;
for (Edge *i=Prev[x];i;i=i->next)
ret+=Query(rl[i->to[0]],rr[i->to[0]],val-i->w)-Query(el[i->to[1]],er[i->to[1]],val-i->w);
return ret;
}
int query(int x)
{
int l=1,r=10*(n-1),mid=(l+r)>>1;
while (l<r)
{
mid=(l+r)>>1;
if (check(x,mid)<k) l=mid+1;
else r=mid;
}
return l;
}
int main()
{
in(n);in(k);int u,v,w;
for (int i=1;i<n;i++)
{
in(u);in(v);in(w);
insert(u,v,w);insert(v,u,w);
e[top].rev=&e[top-1];e[top-1].rev=&e[top];
}
Size=f[0]=n;
get_G(1,0);solve(rt);
for (int i=1;i<=n;i++) printf("%d\n",query(i));
}